How can I calculate draggable position independently from a scrollable droppable area in React using dnd-kit?

huangapple go评论48阅读模式
英文:

How can I calculate draggable position independently from a scrollable droppable area in React using dnd-kit?

问题

我已经尝试过在悬停时计算日历 div 的滚动量,然后手动更改可拖动元素的 transform 样式属性,但没有成功:

function handleDragMove(event) {
    ...

    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)"
}

如果你的问题是如何解决这个偏移问题,你可以尝试在 handleDragMove 函数中修改可拖动元素的 transform 属性以解决滚动时的偏移。这段代码的逻辑看起来是正确的,但可能需要确保 draggableOrder 变量的值是正确的。如果问题仍然存在,可能需要进一步调试和检查其他可能导致问题的因素。

英文:

I created a touch-screen application using React. I am using the dnd-kit library to enable the dragging & dropping of certain divs.

I have a calendar where the days are the columns, and the rows are categories. Each cell is a Droppable area. Draggable items with different lengths are stored in 3 separate containers. I can drag these items on the grid and place them in a specific cell. So far everything works fine.

Now my issue: My calendar grid is wider than the screen, thus I set "overflow-y" to "auto". Now I can scroll and bring the part I want to view into focus. The problem is that when I now drag one of my Draggable elements unto the calendar grid, the calculated position of the Draggable element is offset by the scroll amount. If I scroll 50px to the right, then the Draggable is also 50px right from the position where I am dragging at.

Is there a way to correct this? To ignore the scrolled amount when dragging the Draggable element over the calendar with the Droppable cells? Or to overwrite the default transform attribute to account for this offset (only when over the calendar).

Here is my Draggable element

`
import {useDraggable} from '@dnd-kit/core';
import styled from "styled-components";

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

`

I already tried to somehow calculate the scroll amount of the calendar div when hovering over, and then manually changing the transform style property of the draggable element, but without any success:
`
function handleDragMove(event) {
...

    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)"
}

`

答案1

得分: 0

I found a solution. Here's the translated code:

找到了一种解决方案我确信有更优雅和内置的解决方案但我找到了一种变通方法

我获取可拖动div的子元素并手动覆盖左偏移为了计算偏移量我使用日历div的位置可拖动顺序div多个可拖动元素的原始div池的位置以及事件本身的位置+修正偏移量

这是我如何计算位置的代码

```javascript
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";
}

它可以正常工作(计算时间只需一小部分秒),但我仍然希望有一个更清晰、最好是内置的解决方案。


Please note that I've translated the code part as requested, without any additional content.

<details>
<summary>英文:</summary>

So I kind of found a solution. I&#39;m sure there is a more elegant and built in solution, but I found a workaround:

I get the child element of my draggable div, and manually override the left offset. To calculate the offset, I use the positions of the calendar div, the draggable order div (my original div-pool of multiple draggable elements) and the event itself (+ a fix offset)

Here is how I calculate the position:

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


It works (takes a fraction of a second to calculate), but I would still love to have a cleaner preferably built-in solution.

</details>



huangapple
  • 本文由 发表于 2023年5月25日 20:19:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/76332202.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定