Reputation: 13
Question:
I am trying to create a lasso tool similar to the one in Google's Jamboard using React Konva. However, I've been struggling with several issues for weeks. Despite trying various approaches, including using ChatGPT and Googling, I haven't been able to resolve the problem.
Problem:
The transformer component detaches from the polygon after resizing or transforming.I am receiving multiple warnings related to NaN values for attributes like x, y, width, and height.
Here is the reproducible code
import React, { useEffect, useState, useRef, useCallback } from "react";
import { Stage, Layer, Line, Transformer } from "react-konva";
const ResizableShape = ({ shapeProps, isSelected, onSelect, onChange }) => {
const shapeRef = useRef();
const trRef = useRef();
useEffect(() => {
if (isSelected) {
trRef.current.nodes([shapeRef.current]);
trRef.current.getLayer().batchDraw();
}
}, [isSelected]);
return (
<>
<Line
onClick={onSelect}
onTap={onSelect}
ref={shapeRef}
closed
{...shapeProps}
draggable
onDragEnd={(e) => {
onChange({
...shapeProps,
x: e.target.x(),
y: e.target.y(),
});
}}
onTransformEnd={(e) => {
const node = shapeRef.current;
const scaleX = node.scaleX();
const scaleY = node.scaleY();
node.scaleX(1);
node.scaleY(1);
const newPoints = node.points().map((p, i) => {
return i % 2 === 0 ? p * scaleX : p * scaleY;
});
onChange({
...shapeProps,
points: newPoints,
});
}}
/>
{isSelected && (
<Transformer
ref={trRef}
enabledAnchors={[
"top-left",
"top-right",
"bottom-left",
"bottom-right",
"middle-left",
"middle-right",
"top-center",
"bottom-center",
]}
flipEnabled={false}
boundBoxFunc={(oldBox, newBox) => {
if (Math.abs(newBox.width) < 5 || Math.abs(newBox.height) < 5) {
return oldBox;
}
return newBox;
}}
/>
)}
</>
);
};
export default function KonvaComp() {
const [shapes, setShapes] = useState([
{
id: String(Date.now()),
points: [],
stroke: "blue",
strokeWidth: 5,
tension: 0.5,
lineCap: "round",
lineJoin: "round",
globalCompositeOperation: "source-over",
},
]);
const [selectedId, setSelectedId] = useState(null);
const handleSelect = (id) => {
setSelectedId(id);
};
const handleChange = (newAttrs) => {
const rects = shapes.slice();
const index = rects.findIndex((r) => r.id === newAttrs.id);
rects[index] = newAttrs;
setShapes(rects);
};
const checkDeselect = (e) => {
if (e.target === e.target.getStage()) {
setSelectedId(null);
}
};
return (
<>
<Stage
width={window.innerWidth}
height={window.innerHeight}
onMouseDown={checkDeselect}
onTouchStart={checkDeselect}
>
<Layer>
{shapes.map((shape, i) => (
<ResizableShape
key={i}
shapeProps={shape}
isSelected={shape.id === selectedId}
onSelect={() => handleSelect(shape.id)}
onChange={handleChange}
/>
))}
</Layer>
</Stage>
</>
);
}
Warnings Received:
Konva warning: NaN is not a valid value for "y" attribute. The value should be a number.
Konva warning: NaN is not a valid value for "x" attribute. The value should be a number
Konva warning: NaN is not a valid value for "x width" attribute. The value should be a number
Konva warning: NaN is not a valid value for "height" attribute. The value should be a number
Request:
I need help resolving the following issues:Preventing the transformer component from detaching after transforming the polygon.Fixing the NaN value warnings for various attributes.
Upvotes: 0
Views: 130