使用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
相关产品推荐
相关产品推荐

