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

React-Grid-Layout垂直紧凑布局下实现拖拽交换位置的方法

React-Grid-Layout 垂直紧凑布局下实现同尺寸网格项拖拽交换

核心思路

React-Grid-Layout默认的垂直紧凑逻辑会优先填充上方空隙,导致同尺寸同行列的网格项拖拽时容易重叠。要实现交换效果,需要在拖拽过程中实时检测目标位置的网格项,手动触发位置交换,同时绕过默认的紧凑布局自动调整逻辑。

具体实现步骤

  1. 记录初始拖拽项信息
    在onDragStart事件中保存拖拽项的原始位置与尺寸:

    const [layout, setLayout] = useState(initialLayout);
    let draggedItem = null;
    
    const handleDragStart = (layoutItem) => {
      draggedItem = { ...layoutItem };
    };
    
  2. 实时拦截拖拽过程,检测并触发交换
    使用onDrag事件实时处理,通过鼠标位置计算当前网格坐标,定位目标项后触发位置交换:

    const handleDrag = (currentLayout, _, __, mousePosition) => {
      const rowHeight = 30; // 替换为你的网格行高配置
      // 计算鼠标所在的网格垂直坐标
      const targetY = Math.floor(mousePosition.y / rowHeight);
      // 筛选同x、同尺寸、同目标Y坐标的非拖拽项
      const targetItem = currentLayout.find(item => 
        item.x === draggedItem.x &&
        item.w === draggedItem.w &&
        item.h === draggedItem.h &&
        item.y === targetY &&
        item.i !== draggedItem.i
      );
    
      if (targetItem) {
        // 交换两个项的Y位置
        const updatedLayout = currentLayout.map(item => {
          if (item.i === draggedItem.i) return { ...item, y: targetItem.y };
          if (item.i === targetItem.i) return { ...item, y: draggedItem.y };
          return item;
        });
        setLayout(updatedLayout);
        // 更新拖拽项记录,避免默认布局逻辑干扰
        draggedItem.y = targetItem.y;
      }
    };
    
  3. 禁用默认紧凑布局的自动调整
    在组件中开启useCSSTransforms,并通过onLayoutChange过滤自动更新的布局:

    const handleLayoutChange = (newLayout) => {
      // 拖拽过程中忽略默认布局更新,仅在拖拽结束后同步
      if (!draggedItem) {
        setLayout(newLayout);
      }
    };
    
    return (
      <ReactGridLayout
        layout={layout}
        onDragStart={handleDragStart}
        onDrag={handleDrag}
        onDragEnd={() => { draggedItem = null; }}
        onLayoutChange={handleLayoutChange}
        verticalCompact={true}
        rowHeight={30} // 与上方rowHeight保持一致
        useCSSTransforms={true}
        // 其他必要属性(如cols、width等)
      >
        {/* 渲染你的网格项 */}
      </ReactGridLayout>
    );
    

关键注意事项

  • 确保rowHeight与你的网格配置完全一致,否则坐标计算会出现偏差。
  • 仅对同x坐标、同尺寸的项触发交换逻辑,避免破坏其他布局结构。
  • 若网格项尺寸动态变化,需在handleDrag的目标项筛选条件中同步更新尺寸判断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 17:25:08