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