react hook 小球拖拽

react hook 小球拖拽

可能也就是这个会比vue好点

vue 也可以… 

虽然能用相同的思维实现, 但是确实手感不如vue

使用vue实现不管怎么拖都没问题, 但是react的有时候会出现事件来不及解除, 导致一直跟着鼠标

 

import React, {
  useState,
  useRef,
  useLayoutEffect,
  useCallback,
  useEffect,
  useMemo
} from "react";
import "./A4.css";

const useDrag = (domRef, setPosition) => {
  const mouseStart = useRef({ x: 0, y: 0 });
  const domStart = useRef({ x: 0, y: 0 });

  useEffect(() => {
    const down = (e) => {
      const { x, y } = domRef.current.getBoundingClientRect();
      mouseStart.current = { x: e.x, y: e.y };
      domStart.current = { x, y };
      document.addEventListener("mousemove", move);
      document.addEventListener("mouseup", up);
      console.log("down", x, y);
    };

    const up = () => {
      console.log("up");
      document.removeEventListener("mouseup", up);
      document.removeEventListener("mousemove", move);
    };
    const move = ({ pageX, pageY, x, y }) => {
      console.log("move");
      console.log(pageX, pageY, domStart, mouseStart, x, y);
      const { width, height } = domRef.current.getBoundingClientRect();

      const nx = domStart.current.x + x - mouseStart.current.x;
      const ny = domStart.current.y + y - mouseStart.current.y;
      setPosition({
        x: nx + width / 2,
        y: ny + height / 2,
      });

      domRef.current.style.left = nx + "px";
      domRef.current.style.top = ny + "px";
    };

    const { x, y, width, height } = domRef.current.getBoundingClientRect();
    setPosition({
      x: x + width / 2,
      y: y + height / 2,
    });
    domRef.current.addEventListener("mousedown", down);
  }, []);
};

export default () => {
  const startRef = useRef();
  const endRef = useRef();
  const [startPosition, setStartPosition] = useState({ x: 0, y: 0 });
  const [endPosition, setEndPosition] = useState({ x: 0, y: 0 });
  useDrag(startRef, setStartPosition);
  useDrag(endRef, setEndPosition);

  const linePosition = useMemo(()=>{
    return {
      x1:startPosition.x,
      x2:endPosition.x,
      y1:startPosition.y,
      y2:endPosition.y,
    }
  },[startPosition,endPosition])
  return (
    <div className="wrap">
      <svg className="svg">
        <line
          className="line"
          x1={linePosition.x1}
          y1={linePosition.y1}
          x2={linePosition.x2}
          y2={linePosition.y2}
        ></line>
      </svg>
      <div ref={startRef} className="box"></div>
      <div ref={endRef} className="box"></div>
      A1
    </div>
  );
};

css

.wrap{
    width: 100vw;
    height: 100vh;
    position: absolute;
    top:0
}
.box {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: black;
  cursor: pointer;
  position: absolute;
}
html,
body {
  margin: 0;
  padding: 0;
  width: 100vw;
  height: 100vh;
}
.svg {
  width: 100vw;
  height: 100vh;
  position: absolute;
}

.line {
  stroke: brown;
  stroke-width: 2px;
}

 

hmoban主题是根据ripro二开的主题,极致后台体验,无插件,集成会员系统
自学咖网 » react hook 小球拖拽