Reputation: 1888
So I am using a react-konva to make a canva in my React project, which contains a number of elements.
I wish to allow people to drag the elements around, but only within a range. For example, there may be a ball in a rectangle, and the user can drag the ball around within the rectangle, but can never move it out of the rectangle and it shall be blocked when it reaches the edges of the rectangle.
How can I achieve this? Now it seems the ball just goes wherever it wants without restriction.
PS. I have found the tutorial for that in JS, but it would be better if I can have a react-focus one.
https://konvajs.org/docs/drag_and_drop/Complex_Drag_and_Drop.html
Upvotes: 0
Views: 192
Reputation: 20288
You can achieve this by using the onDragMove
event in react-konva
to check the position of the draggable element and restrict it within a certain boundary. I recommend limiting position into konva instance directly and only then change state of the app/component if you need that.
import React from "react";
import { createRoot } from "react-dom/client";
import { Stage, Layer, Rect, Circle } from "react-konva";
const App = () => {
const stageWidth = 500;
const stageHeight = 500;
const rectWidth = 300;
const rectHeight = 300;
const ballRadius = 20;
const handleDragMove = (e) => {
const ball = e.target;
const newX = ball.x();
const newY = ball.y();
// Restrict movement within the rectangle
const minX = stageWidth / 2 - rectWidth / 2 + ballRadius;
const maxX = stageWidth / 2 + rectWidth / 2 - ballRadius;
const minY = stageHeight / 2 - rectHeight / 2 + ballRadius;
const maxY = stageHeight / 2 + rectHeight / 2 - ballRadius;
// Apply restrictions
if (newX < minX) ball.x(minX);
if (newX > maxX) ball.x(maxX);
if (newY < minY) ball.y(minY);
if (newY > maxY) ball.y(maxY);
};
return (
<Stage width={stageWidth} height={stageHeight}>
<Layer>
{/* Rectangle */}
<Rect
x={stageWidth / 2 - rectWidth / 2}
y={stageHeight / 2 - rectHeight / 2}
width={rectWidth}
height={rectHeight}
fill="lightgray"
/>
{/* Draggable Ball */}
<Circle
x={stageWidth / 2}
y={stageHeight / 2}
radius={ballRadius}
fill="blue"
draggable
onDragMove={handleDragMove}
/>
</Layer>
</Stage>
);
};
const container = document.getElementById("root");
const root = createRoot(container);
root.render(<App />);
https://codesandbox.io/p/sandbox/flamboyant-heisenberg-mrdxwl?file=%2Fsrc%2Findex.js%3A11%2C25
Upvotes: 0