简体   繁体   中英

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

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);
      }}
      onMouseUp={() => {
        setMouseDown(false);
      }}
      onMouseMove={(event) => {
        if (mousedown) handler(event);
      }}
    >
      <div
        style={{
          position: "fixed",
          width: selectionArea.width,
          height: selectionArea.height,
          backgroundColor: "#296CF2",
          top: `${offsetYStart}px`,
          left: `${offsetXStart}px`
        }}
      />
    </div>
  );
}

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?

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);
            }}
            onMouseUp={() => {
                setMouseDown(false);
            }}
            onMouseMove={(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);
        }}
        onMouseUp={() => {
            setMouseDown(false);
        }}
        onMouseMove={(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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM