基于React-rnd实现拖拽调整后列重排的方案咨询
React-Rnd 2x2网格拖拽缩放自动布局示例
下面是一个贴合需求的简易实现,核心通过状态管理控件的位置与尺寸,在拖拽/缩放后自动调整布局,填补空出的空间:
import { useState, useEffect } from 'react'; import { Rnd } from 'react-rnd'; // 模拟权限控制:这里可以替换成实际的权限判断逻辑 const hasAccess = { item1: true, item2: true, item3: false, // 隐藏第三个控件 item4: true, }; const GridRndDemo = () => { // 初始化每个控件的位置、尺寸(基于2x2网格,每列/行占50%) const [items, setItems] = useState([ { id: 'item1', x: 0, y: 0, width: '50%', height: '50%', show: hasAccess.item1 }, { id: 'item2', x: '50%', y: 0, width: '50%', height: '50%', show: hasAccess.item2 }, { id: 'item3', x: 0, y: '50%', width: '50%', height: '50%', show: hasAccess.item3 }, { id: 'item4', x: '50%', y: '50%', width: '50%', height: '50%', show: hasAccess.item4 }, ]); // 调整布局:当控件尺寸变化后,重新排列控件填补空白 const adjustLayout = (updatedItem) => { setItems(prevItems => { // 先更新当前变化的控件 const updatedItems = prevItems.map(item => item.id === updatedItem.id ? updatedItem : item ); // 过滤出需要显示的控件 const visibleItems = updatedItems.filter(item => item.show); if (visibleItems.length <= 1) return updatedItems; // 按行分组,重新计算位置 let currentX = 0; let currentY = 0; const rowHeight = '50%'; const containerWidth = 100; // 用百分比数值计算,方便判断 return updatedItems.map(item => { if (!item.show) return item; // 计算当前控件的宽度数值(去掉%) const itemWidth = parseInt(item.width); // 如果当前行剩余空间不够,移到下一行 if (currentX + itemWidth > containerWidth) { currentX = 0; currentY = currentY === 0 ? 50 : 0; } const newItem = { ...item, x: `${currentX}%`, y: `${currentY}%` }; currentX += itemWidth; return newItem; }); }); }; // 处理缩放事件 const handleResize = (e, direction, ref, delta, position, size) => { const updatedItem = { ...items.find(i => i.id === ref.id), width: `${size.width}%`, height: `${size.height}%`, x: `${position.x}%`, y: `${position.y}%`, }; adjustLayout(updatedItem); }; // 处理拖拽事件 const handleDragStop = (e, d) => { const updatedItem = { ...items.find(i => i.id === e.target.id), x: `${d.x}%`, y: `${d.y}%`, }; adjustLayout(updatedItem); }; return ( <div style={{ width: '100vw', height: '100vh', position: 'relative', border: '1px solid #ccc' }}> {items.map(item => ( item.show && ( <Rnd key={item.id} id={item.id} size={{ width: item.width, height: item.height }} position={{ x: item.x, y: item.y }} bounds="parent" onResizeStop={handleResize} onDragStop={handleDragStop} style={{ border: '2px solid #4285f4', backgroundColor: 'rgba(66, 133, 244, 0.1)' }} > <div style={{ padding: '1rem' }}>{item.id}</div> </Rnd> ) ))} </div> ); }; export default GridRndDemo;
关键逻辑说明
- 用
items状态存储每个控件的位置、尺寸和显示状态,可直接通过hasAccess对象控制哪些控件显示 adjustLayout函数会在控件拖拽/缩放后触发,遍历可见控件,自动计算每行剩余空间,把放不下的控件移到下一行并填充空白- 网格基础单位按百分比设置(每列/行占50%),可根据实际需求调整容器尺寸和单位
内容的提问来源于stack exchange,提问作者user1094183
相关产品推荐
相关产品推荐

