如何使用 dnd-kit 独立于 React 中的可滚动可放置区域计算可拖动位置?

问题描述 投票:0回答:1

我使用 React 创建了一个触摸屏应用程序。我正在使用 dnd-kit 库来启用某些 div 的拖放功能。

我有一个日历,其中日期是列,行是类别。每个单元格都是一个可放置区域。不同长度的可拖动物品存储在 3 个独立的容器中。我可以将这些项目拖动到网格上并将它们放置在特定的单元格中。到目前为止一切正常。

现在我的问题:我的日历网格比屏幕宽,因此我将“overflow-y”设置为“auto”。现在我可以滚动并将我想要查看的部分置于焦点中。问题是,当我现在将 Draggable 元素之一拖动到日历网格时,Draggable 元素的计算位置会因滚动量而偏移。如果我向右滚动 50px,那么 Draggable 也距离我拖动的位置向右 50px。

有办法纠正这个问题吗?使用可放置单元格将可拖动元素拖动到日历上时要忽略滚动量吗?或者覆盖默认变换属性以考虑此偏移(仅当在日历上时)。

这是我的可拖动元素

` 从“@dnd-kit/core”导入{useDraggable}; 从“样式组件”导入样式;

const StyledDraggable = styled.div`
  z-index: 2;
  transform: ${props => props.transform};
  position: ${props => props.position};
  touch-action: manipulation;
`;

export function Draggable(props) {
    const {attributes, listeners, setNodeRef, transform, isDragging} = useDraggable({
        id: props.id,
        data: {
            type: 'draggable',
            droppableId: props.id,
            date: props.startDate
        }
    });

    const tForm = transform ?
        `translate3d(${transform.x}px, ${transform.y}px, 0)` : undefined;

    const position = isDragging ? 'absolute' : null;

    return (
        <StyledDraggable ref={setNodeRef} transform={tForm} position={position} {...listeners} {...attributes}>
            {props.children}
        </StyledDraggable>
    );
}

`

我已经尝试以某种方式计算悬停时日历 div 的滚动量,然后手动更改可拖动元素的转换样式属性,但没有成功: ` 函数handleDragMove(事件){ ...

    let calendar = document.querySelector("#scrollContainer")
    let draggableElement = document.getElementById(active.id).parentElement
    let transformation = window.getComputedStyle(draggableOrder, null).transform
    let xOffset = parseInt(transformation.split(",")[4])
    let yOffset = parseInt(transformation.split(",")[5])
    draggableElement.style.transform = "translate3d(" + (xOffset - calendar.scrollLeft) + "px, " + yOffset + "px, 0)"
}

`

reactjs react-hooks draggable droppable dnd-kit
1个回答
0
投票

所以我找到了一个解决方案。我确信有一个更优雅的内置解决方案,但我找到了一个解决方法:

我获取可拖动 div 的子元素,并手动覆盖左侧偏移量。为了计算偏移量,我使用日历 div、可拖动顺序 div(我的多个可拖动元素的原始 div 池)和事件本身(+ 固定偏移量)的位置

这是我计算位置的方法:

handleDragMove(event) {
    ...
    const calendarRect = document.querySelector("#innerCalendar").getBoundingClientRect();
    const draggableOrder = document.getElementById(active.id).parentElement.getBoundingClientRect();
    const dropBoxRect = document.getElementById(active.data.current.container).getBoundingClientRect();
    const x = event.delta.x + calendarRect.left - draggableOrder.left + dropBoxRect.left - 250;
    document.getElementById(active.id).style.left = x + "px";
}

它可以工作(需要几分之一秒的时间来计算),但我仍然希望有一个更干净、最好是内置的解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.