I am trying to make a selection when a button is clicked.
I added a log function to place div elements in x,y coordinates.
As you can see in this image, when I stretch the selection area the coordinates are displayed normally:
But when I try to shrink the selection area, I get the wrong offsetX
and offsetY
.
I have no idea why this is happening and I hope to get a hint from you.
I've created an codesandbox, you can check it out: https://codesandbox.io/s/blue-shape-hp3ho?file=/src/App.tsx:0-1967
App.tsx from codesandbox:
import React, { useEffect, useState } from "react";
import css from "./App.module.css";
import "./styles.css";
const log: Function = (x: number, y: number) => {
let div = document.createElement("div");
div.style.position = "fixed";
div.style.width = "3px";
div.style.height = "3px";
div.style.backgroundColor = "red";
div.style.borderRadius = "5px";
div.style.zIndex = "4000000000000";
div.style.left = `${x}px`;
div.style.top = `${y}px`;
document.body.appendChild(div);
};
export default function App() {
const [mousedown, setMouseDown] = useState(false);
const [offsetXStart, setOffsetXStart] = useState(0);
const [offsetYStart, setOffsetYStart] = useState(0);
const [offsetX, setOffsetX] = useState(0);
const [offsetY, setOffsetY] = useState(0);
const [selectionArea, setSelectionArea] = useState({
width: "0",
height: "0"
});
useEffect(() => {
setSelectionArea({
width: `${offsetX - offsetXStart}px`,
height: `${offsetY - offsetYStart}px`
});
}, [offsetX, offsetY]);
const handler: any = (event: any) => {
const nativeEvent: any = event.nativeEvent;
if (offsetYStart === 0 && offsetXStart === 0) {
setOffsetXStart(nativeEvent.offsetX);
setOffsetYStart(nativeEvent.offsetY);
}
setOffsetX(nativeEvent.offsetX);
setOffsetY(nativeEvent.offsetY);
log(nativeEvent.offsetX, nativeEvent.offsetY);
};
return (
<div
className={css.selection__tool}
onMouseDown={() => {
setMouseDown(true);
}}
onm ouseUp={() => {
setMouseDown(false);
}}
onm ouseMove={(event) => {
if (mousedown) handler(event);
}}
>
<div
style={{
position: "fixed",
width: selectionArea.width,
height: selectionArea.height,
backgroundColor: "#296CF2",
top: `${offsetYStart}px`,
left: `${offsetXStart}px`
}}
/>
</div>
);
}
CodePudding user response:
This is just a wild stab in the dark, but I notice the blue square is flickering between two sizes as you shrink it. And looking at the code, you are defining width and height two different ways, which could be out of sync potentially, thus causing the Dom to be working against itself?
width: `${offsetX - offsetXStart}px`,
and
width: selectionArea.width,
possibly eliminating one of these, and having a single piece of code that defines width & height might fix the issue?
CodePudding user response:
You put your "selectionArea" inside a div with a css class "selection__tool". Instead, place them on the same level:
return (
<div>
<div
className={css.selection__tool}
onMouseDown={() => {
setMouseDown(true);
}}
onm ouseUp={() => {
setMouseDown(false);
}}
onm ouseMove={(event) => {
if (mousedown) handler(event);
}}
/>
<div
style={{
position: "fixed",
width: selectionArea.width,
height: selectionArea.height,
backgroundColor: "#296CF2",
top: `${offsetYStart}px`,
left: `${offsetXStart}px`
}}
/>
</div>
);
or add pointer-events: none;
to your "selectionArea".
return (
<div
className={css.selection__tool}
onMouseDown={() => {
setMouseDown(true);
}}
onm ouseUp={() => {
setMouseDown(false);
}}
onm ouseMove={(event) => {
if (mousedown) handler(event);
}}
>
<div
style={{
position: "fixed",
width: selectionArea.width,
height: selectionArea.height,
backgroundColor: "#296CF2",
top: `${offsetYStart}px`,
left: `${offsetXStart}px`,
pointerEvents: 'none'
}}
/>
</div>
);