You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用dnd-kit拖拽时元素移动速度快于光标位置偏移如何解决?

问题原因
  • SortableContext的items与SortableItem的id不匹配:你当前SortableContext传入的items是bedsSorted.map(bed => bed.order.toString()),但每个SortableItem的id用的是数组索引index.toString(),两者值不一致的情况下dnd-kit无法正确计算元素位置,导致拖拽位移计算错误,出现元素移动速度和光标不同步的问题。
  • 未正确实现SortableItem的样式绑定:自定义的SortableItem组件如果没有正确接收并应用dnd-kit返回的transform、transition属性,以及挂载ref的话,会导致拖拽时的位置偏移计算失效。
  • 父容器坐标干扰:外层Grid容器如果设置了transform、缩放、或者非static定位,会影响dnd-kit默认基于视口的坐标计算,导致位移量计算偏大,看起来元素移动速度比光标快。
  • 未配置合适的碰撞检测规则:默认的碰撞检测算法和Grid布局不匹配,也会导致元素停靠位置计算错误。
修复方案
  • 第一步:统一id规则,把SortableItem的id和SortableContext的items取值保持一致,同时建议不要用数组索引做key,改用业务唯一值:
function GridWard(){
  return(
    <Grid container spacing={3} >
      <DndContext 
        onDragEnd={orderUpdate}>
        <SortableContext items={bedsSorted.map(bed => bed.order.toString())}>
          <Droppable id="droppable">
            {
              bedsSorted.map((bed) => {
                return(
                  <SortableItem
                    key={bed.order.toString()}
                    id={bed.order.toString()}
                  >
                    <BedButton name={bed.name} onClick={() => editBed(bed)}
                      type="edit" active={bed.active} deleteCallBack={(e:Event) => deleteBed(e, bed)}
                      gender={bed.gender === 0 ? "male" : bed.gender === 1 ? "female" : "any"} 
                    />                                               
                  </SortableItem>
                )
              })
            } 
          </Droppable>
        </SortableContext>
      </DndContext>
    </Grid>
  );
}
  • 第二步:检查SortableItem组件的实现,确保正确绑定ref、transform、transition属性,示例正确的SortableItem写法:
import {useSortable} from '@dnd-kit/sortable';
import {CSS} from '@dnd-kit/utilities';

function SortableItem(props) {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
  } = useSortable({id: props.id});
  
  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
  };
  
  return (
    <div ref={setNodeRef} style={style} {...attributes} {...listeners}>
      {props.children}
    </div>
  );
}
  • 第三步:给DndContext配置适配Grid布局的碰撞检测规则,存在缩放场景时补充修饰器修正坐标:
import {rectIntersection} from '@dnd-kit/collision';
import {adjustScale} from '@dnd-kit/modifiers';

// 修改DndContext配置
<DndContext 
  onDragEnd={orderUpdate}
  collisionDetection={rectIntersection}
  modifiers={[adjustScale]}
>
  {/* 原有内容不变 */}
</DndContext>
  • 第四步:排查外层Grid容器的样式,避免在Grid父级设置会影响坐标计算的transform、perspective等属性,如果必须设置,需要在自定义修饰器里减去对应容器的偏移值。

内容的提问来源于stack exchange,提问作者subharb

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 20:57:01