I am working on drawing a rectangle shape on a browser using divs on React project. Everything is working as expected but when I am adding the margin to the parent base
and then drawing the box the boxes are drawing with some space between the mouse courser and the actual box.
The same thing happening if I am adding a top margin to a base
Here is my code:
const divRef = useRef<HTMLDivElement>(null);
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 [visual, setVisualRect] = useState(false);
const mouseDown = (event: any) => {
set_last_mousex(event.clientX);
set_last_mousey(event.clientY);
setMouseDown(true);
};
const mouseMove = (event: any) => {
set_mousex(event.clientX);
set_mousey(event.clientY);
visualRect();
};
const visualRect = () => {
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);
setVisualRect(true);
}
};
const mouseUp = () => {
setMouseDown(false);
setVisualRect(false);
};
return (
<div className={"base"}>
<div className={"container"} ref={divRef}>
<div
className={"drawArea"}
onm ouseDown={mouseDown}
onm ouseUp={mouseUp}
onm ouseMove={mouseMove}
>
{visual &&
(<div className={"rectBox"} style={{left: rectx, top: recty, width:rectwidth, height:rectheight}}></div>)
}
</div>
</div>
</div>
);
Here is the CSS:
.base {
width: 600px;
height: 500px;
/* this margin is causing issue */
margin-left: 200px;
}
.drawArea {
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
}
.rectBox {
position: absolute;
border: 3px solid #581d1d;
}
.container {
height: 500px;
width: 100%;
background-color: rgb(219, 219, 219);
position: relative;
}
I also created sandbox demo
CodePudding user response:
@CBroe is correct, clientX and clientY is relative to viewport. What you can do is subtract it from the element's viewport X & Y so you get the proper coordinates relative to the element's X & Y
For example, if the element's X is 200px
and the click is 245px
, both relative to viewport, if you compute 245px - 200px
you get 45px
which is relative to the element because you got rid of the element's X from the click's X.
const mouseDown = (event: any) => {
const x = event.clientX - event.currentTarget.getBoundingClientRect().left
const y = event.clientY - event.currentTarget.getBoundingClientRect().top
set_last_mousex(x);
set_last_mousey(y);
setMouseDown(true);
};
//...
const mouseMove = (event: any) => {
const x = event.clientX - event.currentTarget.getBoundingClientRect().left
const y = event.clientY - event.currentTarget.getBoundingClientRect().top
set_mousex(x);
set_mousey(y);
visualRect();
};
getBoundingClientRect
: https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect