1
votes

On Konva (React-Konva to be precise) there is a Stage with a Layer with an Image. Clicking on that Image gives the position of the Click on that Image. But after Dragging (either the Stage or the Image), the position is different.

In React-Konva code this looks basically like this:

<Stage width={2000} height={2000} draggable={true}>
    <Layer>
        <MyImage url="_some_url_pointing_to_a_png_" />
    </Layer>
</Stage>

The MyImage Component:

const MyImage = (props) => {
    const url = props.url;
    const [image, status, width, height] = useImage(url);

    return (
        <Image
            image={image}
            width={width}
            height={height}
            onClick={clickHandler}
        />
    );
};

(Yes, I modified the useImage React-Hook to also return width and height)

The clickHandler is quite simple:

const clickHandler = (e) => {
    const stage = e.target.getStage();
    const stageLocation = stage.getPointerPosition();
    console.table(stageLocation);
};

The problem is that clicking on that image does give me a position, which seems to look ok. But when I drag the image, due to 'draggable={true}' on the Stage (so, 'drag the Stage' to be precise) and then click on the same position in the Image again, I get another location. This is probably obvious because it gives me the position of the Click on the Stage and not the position of the Click on the Image.

When making the Stage not Draggable and the Image Draggable, then the same problem applies.

So, question remains:

How to get the position of the Click on the Image when it (or its Stage) is Draggable?

1
What exactly do you mean by "position of the Click on the Image"? Do you need a position of the pointer relative to image position? stage.getPointerPosition() returns absolute position of the pointer.lavrton
'Relative' and 'Absolute' are maybe confusing terms in this. I mean that when I have an Image of an Elephant, and I click on the Trunk, and then I move (Drag) the image in the Stage (because Image is larger than visible Stage), and I click on the Trunk again, then I want the same position.BertC

1 Answers

1
votes

Think I found the solution. The attrs of the Image contain the offset of that Image in the Stage. (or in the Layer?)

Code by which you get the position on an Image which is in a Layer which is in a Draggable Stage:

const clickHandler = (e) => {
    const stage = e.target.getStage();
    const pointerPosition = stage.getPointerPosition();
    const offset = {x: e.target.attrs.x, y: e.target.attrs.y};

    const imageClickX = pointerPosition.x - offset.x;
    const imageClickY = pointerPosition.y - offset.y;

    console.table({x: imageClickX, y: imageClickY});
};

However, this piece of code only works if the image is draggable also. In fact you're dragging the image probably. If you have a draggable Stage and a non-draggable-Image, then the offset is found in the Stage:

const stage = e.target.getStage();
console.table({offsetX: stage.attrs.x, offsetY: stage.attrs.y});

(And I'll update this answer again if I encounter new clues on the final solution :-), this is getting quite a saga...)

I'm more than interested if anybody sees any pitfalls with this solution.

Thanks,

Bert