konvajs / react-konva

React + Canvas = Love. JavaScript library for drawing complex canvas graphics using React.
https://konvajs.github.io/docs/react/
MIT License
5.8k stars 260 forks source link

Konva – How to Make a Stage Fill the View and Implement Zoom In/Out Based on Position and Current Scale, Along with Drag Boundaries? #808

Closed ersathCodes closed 3 months ago

ersathCodes commented 4 months ago
useEffect(() => {
    let stage = stageRef.current;

    if (stage) {
        const padding = 60;
        const clientRect = stage.getClientRect({ relativeTo: stage });
        const shapeRect = {
            x: clientRect.x - padding,
            y: clientRect.y - padding,
            width: clientRect.width + (2 * padding),
            height: clientRect.height + (2 * padding)
        };
        const viewRect = {
            width: stage.width() < stage.container().offsetWidth ? stage.width() : stage.container().offsetWidth,
            height: stage.height() < stage.container().offsetHeight ? stage.height() : stage.container().offsetHeight
        };

        shape.current = shapeRect;

        const widthRatio = viewRect.width / shapeRect.width;
        const heightRatio = viewRect.height / shapeRect.height;

        const scale = widthRatio > heightRatio ? heightRatio : widthRatio;
        const centeringAjustment = {
            x: (viewRect.width - shapeRect.width * scale) / 2,
            y: (viewRect.height - shapeRect.height * scale) / 2
        };

        const finalPosition = {
            x: centeringAjustment.x + (-shapeRect.x * scale),
            y: centeringAjustment.y + (-shapeRect.y * scale)
        };

        scaleToFit.current = {
            x: finalPosition.x,
            y: finalPosition.y,
            width: shapeRect.width,
            height: shapeRect.height,
            scale: scale
        };
        console.log('scale to fit ', scaleToFit.current);
        setStageData((preVal) => ({
            ...preVal,
            x: finalPosition.x,
            y: finalPosition.y,
            scale: scale
        }))
    }
    else
        return;
}, [enableView]);

The above code helps with scaling and positioning the stage. Now, I want to allow the user to zoom the stage while keeping it within boundaries after it has been positioned and scaled. How can I achieve this?

lavrton commented 4 months ago

What did you try? What is not working? What are "boundaries"?

ersathCodes commented 4 months ago

I recently read the article How to preview large stages on canvas with Konva. It describes exactly what I want to implement in my app, but I've encountered some issues.

Firstly, if a user clicks to open a preview, I want to show the entire stage and its shapes. To achieve this, I calculate the appropriate scale and set the position accordingly. I then center the content based on these calculations, allowing the user to view the entire stage. This part works well.

Additionally, I came across this CodeSandbox example where the image within the stage is zoomable but cannot be moved apart from dragging the image. My requirement is to enable both zoom and drag within the set position and scale.

So now, I want to implement the image behavior described in that example in my stage.

lavrton commented 3 months ago

I still don't get what is your specific question. The last sandbox your shared is not solving your problem?

ersathCodes commented 3 months ago

I’m happy to let you know that I’ve finally found the answer I was looking for. I appreciate your attempt to help, and your support was valuable throughout this process. Thanks again for your assistance!