【发布时间】:2021-07-31 04:57:43
【问题描述】:
这是我的第一个 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', preventBehavior, {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
【问题讨论】:
标签: javascript reactjs events draggable drag