Home > OS >  Why am I getting wrong offsetX and offsetY in my event handler?
Why am I getting wrong offsetX and offsetY in my event handler?

Time:11-19

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>
);

CSS pointer-events Property

  • Related