如何解决为什么我在 React 中的可拖动组件在鼠标移动前移动到光标之前?
这是我的第一个 Stack Overflow 问题,所以请耐心等待,如果您需要更多信息,请告诉我!我基本上是在重新创建一个简化的 Beyond20 可交互地图供 Dungeon Master 使用。为首次初级开发应用构建项目组合。
无论如何,我已经用纯背景颜色的 div 制作了可移动的“碎片”,带有简短的文本名称,可以在板上的地图图像周围移动。与其导入像 React DnD 这样的预构建库,我想从头开始执行此操作以更好地了解机制。我将我的移动逻辑存储在组件 Draggable(如下)中。然而,每当我拖动一个“片段”时,该片段会逐渐移动到光标的前面(注意:它不会像我在其他地方读到的那样落后,它会向光标移动的任何方向缓慢向前滑动),并且这种行为会发生在我测试过的每个显示器屏幕上,除了我写代码的原始显示器。还要注意的是,可拖动组件在任何拖动事件上都会从光标处移动一段可复制的距离,这意味着,如果我拖动元素,例如 300 像素,它最终将始终位于光标前面的相同距离处。
我希望这是有道理的。如果我能澄清任何事情,请告诉我。任何和所有的建议都非常感谢!
可拖动组件:
import React,{ useState,useEffect,useRef } from 'react';
function Draggable({
children,position,updatePosition,deleteIcon,id
}) {
const [drop,setDrop] = useState({ x: position.x,y: position.y })
const dragRef = useRef()
const handlePointerDown = (e) => {
window.addEventListener('pointermove',handleDragMove);
window.addEventListener('pointerup',handlePointerUp);
};
const handleDragMove = (e) => {
dragRef.current.style.left = `${dragRef.current.offsetLeft + e.movementX}px`
dragRef.current.style.top = `${dragRef.current.offsetTop + e.movementY}px`
};
const handlePointerUp = (e) => {
const aspectBox = document.getElementById('aspectRatioBox')
const bounding = dragRef.current.getBoundingClientRect();
if(bounding.x < 100 && bounding.y < 100) {
//Below conditional is for deleting an Icon if dropped within a specific area on page
try {
deleteIcon(id)
} catch(exception) {
console.log('Unable to delete icon',exception)
}
} else if (drop.x !== dragRef.current.style.left && drop.y !== dragRef.current.style.top) {
//This is for updating the position in the server through socket.io and saving to database
setDrop({
x: `${dragRef.current.style.left.replace(/px/g,'')/aspectBox.clientWidth*100}%`,y: `${dragRef.current.style.top.replace(/px/g,'')/aspectBox.clientHeight*100}%`
})
}
window.removeEventListener('pointermove',handleDragMove);
window.removeEventListener('pointerup',handlePointerUp);
}
const preventBehavior =(e) => {
e.preventDefault();
}
useEffect(() => {
window.addEventListener('touchmove',preventBehavior,{passive: false})
return () => {
window.removeEventListener('pointerup',handlePointerUp)
window.removeEventListener('touchmove',{passive: false})
window.removeEventListener('pointermove',handleDragMove);
window.removeEventListener('pointerup',handlePointerUp);
}
},[])
const firstRender = useRef(true);
useEffect(() => {
if(!firstRender.current) {
updatePosition({
x: drop.x,y: drop.y
},id)
}
},[drop.x,drop.y] )
useEffect(() => { firstRender.current = false },[])
return (
<div
onPointerDown={handlePointerDown}
style={{top: position.y,left: position.x}}
className="draggableBox"
ref={dragRef}
>
{children}
</div>
)
}
export default Draggable
解决方法
因此,经过许多小时的 Google Foo 失败后,我找到了解决问题的可靠方法。
我不相信这解决了我的根本问题是可拖动元素领先于光标,但我相信这与我通过 e.movementX 和 e.movementY 更新位置的附加性质有关。
const handlePointerDown = (e) => {
const { left,top } = dragRef.current.getBoundingClientRect()
posRef.current = {
x: left - e.clientX,y: top - e.clientY
}
window.addEventListener('pointermove',handleDragMove);
window.addEventListener('pointerup',handlePointerUp);
e.stopPropagation();
e.preventDefault();
};
const handleDragMove = (e) => {
const aspectBox = document.getElementById('aspectRatioBox').getBoundingClientRect()
dragRef.current.style.left = `${(e.clientX + posRef.current.x - aspectBox.left)/aspectBox.width*100}%`
dragRef.current.style.top = `${(e.clientY + posRef.current.y - aspectBox.top)/aspectBox.height*100}%`
e.stopPropagation();
e.preventDefault();
};
我通过可拖动元素在其中移动的框的增量和光标的 e.Client 位置获得可拖动元素的相对位置。我添加了一个 ref posRef,它允许更精确地移动图标,而不是立即将光标捕捉到图标的左上角。
希望这能帮助任何发现自己处于类似情况的人!!!
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。