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

如何避免DragOverlay在Dropzone内放置时触发返回原点动画?

解决方案

要实现你的需求,核心是区分拖拽结束时的放置有效性,并分别处理DragOverlay的显示/隐藏逻辑,同时配合数据更新移除原位置的拖拽项(避免原元素播放返回动画)。具体实现如下:

1. 补充状态与标识

  • 添加状态跟踪Dropzone中的已放置项
  • 给<Droppable>设置唯一id,用于判断是否为有效放置目标

2. 完善拖拽结束逻辑

在onDragEnd中判断放置是否有效:

  • 有效放置:将拖拽项从原列表移到Dropzone列表,直接隐藏DragOverlay
  • 无效放置:延迟清空activeId,让DragOverlay完成返回原点的动画后再隐藏

3. 完整代码示例

import { useState } from "react";
import { DndContext, Draggable, Droppable, DragOverlay } from "@dnd-kit/core";

function Item({ value }) {
  return (
    <div style={{ padding: "8px", margin: "8px 0", background: "#eee" }}>
      {value}
    </div>
  );
}

export default function App() {
  const [items, setItems] = useState(["1", "2", "3", "4", "5"]);
  const [droppedItems, setDroppedItems] = useState([]);
  const [activeId, setActiveId] = useState(null);

  return (
    <DndContext onDragStart={handleDragStart} onDragEnd={handleDragEnd}>
      {/* 原拖拽项列表 */}
      <div style={{ marginBottom: "20px" }}>
        {items.map((id) => (
          <Draggable key={id} id={id}>
            <Item value={`Item ${id}`} />
          </Draggable>
        ))}
      </div>

      {/* DragOverlay */}
      <DragOverlay>
        {activeId && <Item value={`Item ${activeId}`} />}
      </DragOverlay>

      {/* 目标Dropzone */}
      <Droppable id="dropzone">
        <div style={{ border: "solid", padding: "15px" }}>
          Drop here
          {droppedItems.map((id) => (
            <Item key={id} value={`Item ${id}`} />
          ))}
        </div>
      </Droppable>
    </DndContext>
  );

  function handleDragStart(event) {
    setActiveId(event.active.id);
  }

  function handleDragEnd(event) {
    const { active, over } = event;
    // 判断是否放置到了有效Dropzone
    const isDropValid = over?.id === "dropzone";

    if (isDropValid) {
      // 有效放置:更新列表,直接隐藏DragOverlay
      setItems((prev) => prev.filter((id) => id !== active.id));
      setDroppedItems((prev) => [...prev, active.id]);
      setActiveId(null);
    } else {
      // 无效放置:等待返回动画结束后再隐藏DragOverlay
      setTimeout(() => {
        setActiveId(null);
      }, 300); // 匹配@dnd-kit默认动画时长
    }
  }
}

关键说明

  • 有效放置时:通过更新列表数据,将拖拽项从原列表移除,避免原<Draggable>元素触发返回动画;同时直接清空activeId让DragOverlay立刻消失。
  • 无效放置时:延迟清空activeId,让<DragOverlay>组件自动播放返回原点的动画,动画结束后再隐藏它。
  • 给<Droppable>设置id是为了精准判断放置目标,避免误判其他可放置区域。

内容的提问来源于stack exchange,提问作者Snæbjörn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 19:28:13