我正在使用 1.0.0-rc。
在drag-around-naive
:
const boxTarget = {
drop(props, monitor, component) {
const item = monitor.getItem();
const delta = monitor.getDifferenceFromInitialOffset();
const left = Math.round(item.left + delta.x);
const top = Math.round(item.top + delta.y);
component.moveBox(item.id, left, top);
}
};
目前看起来我需要从原始项目的页面获取偏移量,然后我可以找到我放置的页面的偏移量,然后我需要从页面中找到放置容器的偏移量,然后做该计算和我在放置目标容器中的相对位置。
对于非常常见的事情来说,这似乎需要做很多工作......
似乎getClientOffset
返回了相对于视口的位置。 那么我所要做的就是在我的放置目标中找到我的偏移量。 你认为它仍然值得拥有一个相对于放置目标的便捷方法吗?
是的,我想我们可以用这个来对称。 目前,您可以只使用findDOMNode(component).getBoundingClientRect()
,但如果有更多人支持语音,我不介意添加此功能。 让我们保持开放,看看其他人怎么说。
我也想要这样的东西。 我需要获取放置目标的边界矩形/坐标,因此当我将某物悬停在其上时,我可以计算它是否位于放置目标内的左侧、右侧、顶部或底部。
相对坐标可用于其他用例。 对于类似 Trello 的应用程序,当您将卡片拖到列表上时,当悬停在放置区域底部附近时列表会滚动到底部,而在悬停在顶部附近时会向上滚动。
在用户空间上实现很简单。
此外,我依稀记得读到访问边界矩形会触发浏览器中的回流并且有些昂贵。 不确定是否仍然如此。
我不认为有一种方法可以在不实际访问getBoundingClientRect
情况下执行此操作,因为您永远不知道该项目是否移动。
对于类似 Trello 的应用程序,当您将卡片拖到列表上时,当悬停在放置区域底部附近时列表会滚动到底部,而在悬停在顶部附近时会向上滚动。
这是一个很好的用例。
性能损失确实很重要,如果将其添加到 React DnD 但您的应用程序不使用它,则会被浪费掉。 因此,我不想将此添加到 React DnD。
在用户空间中很容易实现,您将能够执行诸如限制getBoundingClientRect
调用之类的操作,或者将相关的滚动代码放入动画帧中。
我愿意将“在底部悬停时滚动”_作为示例_添加到可排序压力测试中。 这将涉及在容器级别添加另一个放置目标,该目标仅侦听hover
并在动画帧内滚动。
但是,由于上述原因,我不会将 DOM 坐标方法添加到 React DnD。
@gaearon我对通用解决方案感兴趣。 我们如何直接使用react-dnd-html5-backend
而不是getBoundingClientRect
?
我通过将DropTargetMonitor
函数getInitialSourceClientOffset
和getSourceClientOffset
传递给我的onDrop
事件中的回调函数来解决这个问题。 这样,我的回调函数就可以计算出与视口相关的正确坐标。
// some code before...
const [, dropRef] = useDrop({
accept: 'STICKY',
drop(item, monitor) {
move(
item.id,
monitor.getInitialSourceClientOffset(),
monitor.getSourceClientOffset()
);
},
});
// I'm updating my state with npm immer (immutable helper) throuthg the produce function...
const move = (id, initialPosition, finalPosition) => {
setList(
produce(list, draft => {
list.map(item => {
if (item.id === id) {
item.position = getCorrectDroppedOffsetValue(
initialPosition,
finalPosition
);
}
return item;
});
})
);
};
// and finally, my getCorrectDroppedOffsetValue function
const getCorrectDroppedOffsetValue = (initialPosition, finalPosition) => {
// get the container (view port) position by react ref...
const dropTargetPosition = ref.current.getBoundingClientRect();
const { y: finalY, x: finalX } = finalPosition;
const { y: initialY, x: initialX } = initialPosition;
// calculate the correct position removing the viewport position.
// finalY > initialY, I'm dragging down, otherwise, dragging up
const newYposition =
finalY > initialY
? initialY + (finalY - initialY) - dropTargetPosition.top
: initialY - (initialY - finalY) - dropTargetPosition.top;
const newXposition =
finalX > initialX
? initialX + (finalX - initialX) - dropTargetPosition.left
: initialX - (initialX - finalX) - dropTargetPosition.left;
return {
x: newXposition,
y: newYposition,
};
};
findDOMNode
不适用于功能组件,并且useDrop#drop
不会传入任何component
。现在如果我想获得我的组件的ref
将其单独存储并手动调用drop连接器以传递它。 有没有更简洁的方法来做到这一点?
function useCustomDrop(onDrop: (info: unknown, xy: Point) => void) {
const ref = useRef<Element>();
const [, dropTarget] = useDrop<any, void, unknown>({
accept: 'item-type',
drop(item, monitor) {
const offset = monitor.getSourceClientOffset();
if (offset && ref.current) {
const dropTargetXy = ref.current.getBoundingClientRect();
onDrop(item.data, {
x: offset.x - dropTargetXy.left,
y: offset.y - dropTargetXy.top,
});
}
}
});
return (elem) => {
ref.current = elem;
dropTarget(ref);
};
}
@quanganhtran请问您有愿意分享的完整代码示例吗?
@dendrochronology
一个人为的例子: https :
当我们不必自己存储ref
时,API 会更好( useGlobalDrop
vs useLocalDrop
)。 现在,如果只有ref
,我假设react-dnd
已经获得,附加到monitor
对象〜某处(可在drop
,我没有意见在哪里),它会解决这个问题。
此解决方案不可靠,尤其是当您放大浏览器或更改设备分辨率时。 任何的想法?
我有同样的问题@sepehr09
只是经过几次谷歌搜索后路过......原始问题的任何更新? (获取相对于放置目标的放置项目的 x/y)
我想我会加入那些需要这个的名单。 请问有什么帮助吗?
我觉得这个功能很有必要,需要在库中添加。 现在,任何人使用它,请帮助我们!
最有用的评论
是的,我想我们可以用这个来对称。 目前,您可以只使用
findDOMNode(component).getBoundingClientRect()
,但如果有更多人支持语音,我不介意添加此功能。 让我们保持开放,看看其他人怎么说。