Issue
I am using react with typescript. In my project, I am trying to draw multiple rectangles on my SVG. The first rectangle is easily drawn but when I am trying to draw another rectangle the previous one will disappear and then the new one is drawn. How do I maintain the previously drawn rectangle in a state and then render them?
complete sandbox link here is my code:
const svgRef = useRef<SVGSVGElement>(null);
const divRef = useRef<HTMLDivElement>(null);
const { xCord, yCord } = useMousePosition({ divRef });
const [mousedown, setMouseDown] = useState(false);
const [last_mousex, set_last_mousex] = useState(0);
const [last_mousey, set_last_mousey] = useState(0);
const [mousex, set_mousex] = useState(0);
const [mousey, set_mousey] = useState(0);
const [rectx, setrectx] = useState(0);
const [recty, setrecty] = useState(0);
const [rectwidth, setrectwidth] = useState(0);
const [rectheight, setrectheight] = useState(0);
const mouseDown = () => {
set_last_mousex(xCord);
set_last_mousey(yCord);
setMouseDown(true);
};
const mouseUp = () => {
setMouseDown(false);
};
const mouseMove = () => {
set_mousex(xCord);
set_mousey(yCord);
};
const addRectangle = () => {
if (mousedown) {
const width = Math.abs(mousex - last_mousex);
const height = Math.abs(mousey - last_mousey);
const rx = mousex < last_mousex ? mousex : last_mousex;
const ry = mousey < last_mousey ? mousey : last_mousey;
rectx!==rx && setrectx(rx);
recty!==ry && setrecty(ry);
rectheight!==height && setrectheight(height);
rectwidth!==width && setrectwidth(width);
return (
<rect
x={rx}
y={ry}
height={height}
width={width}
/>
);
}
};
return (
<div className="App" ref={divRef}>
<svg
id="svg"
ref={svgRef}
onMouseDown={mouseDown}
onMouseUp={mouseUp}
onMouseMove={mouseMove}
>
{addRectangle() ? (
addRectangle()
) : (
<rect
x={rectx}
y={recty}
height={rectheight}
width={rectwidth}
/>
)}
</svg>
</div>
);
Solution
You can achieve it like this
- Save the rectangles to another state array
const [rectArray, setRectArray] = useState<Array<JSX.Element>>([]);
const addRectangle = () => {
if (mousedown) {
const width = Math.abs(mousex - last_mousex);
const height = Math.abs(mousey - last_mousey);
const rx = mousex < last_mousex ? mousex : last_mousex;
const ry = mousey < last_mousey ? mousey : last_mousey;
rectx !== rx && setrectx(rx);
recty !== ry && setrecty(ry);
rectheight !== height && setrectheight(height);
rectwidth !== width && setrectwidth(width);
setRectArray((prevArr) => [
...prevArr,
<rect x={rx} y={ry} height={height} width={width} />
]);
}
};
- You should call
addRectangle
at the last line ofmouseUp
const mouseUp = () => {
setMouseDown(false);
addRectangle();
};
- Then you can iterate over them to show all the rectangles
return (
<div className="App" ref={divRef}>
<svg
id="svg"
ref={svgRef}
onMouseDown={mouseDown}
onMouseUp={mouseUp}
onMouseMove={mouseMove}
>
{rectArray.map((rect) => rect)}
</svg>
</div>
);
Answered By - Amila Senadheera
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.