图片
拖拽模块我采用了 movable, 并研究了它的大量 API,最终实现了我想要的效果,当然我还设计了一套数据结构,如果大家对可视化搭建感兴趣,也可以扩展成自己的拖拽搭建结构。
图片
元素多选我采用了 selecto 模块,成组管理器我采用了 @moveable/helper, 当然在使用这些库的时候也踩了不少坑,好在已经完美解决。
下面分享一个简单的数据结构,以支持我们的元素自由搭建:
const schema = { "Button": { id: 'wep_001', name: 'Button', type: 'base', // 基础类型组件 base: { width: 120, height: 36, transform: 'translate(100px,100px)' } }, "Image": { id: 'wep_002', name: 'Image', type: 'base', // 基础类型组件 base: { width: 120, height: 120, url: '', transform: 'translate(300px,160px)' } }}export default schema
图片
对于工具条的实现,我做了统一的封装,以便后期可能更低成本的维护和管理:
接下来看看工具条的配置:
const toolbar = { base: [ { key: 'group', icon: <GroupOutlined />, text: '成组', }, { key: 'ungroup', icon: <UngroupOutlined />, text: '取消成组' }, { key: 'left', icon: <AlignLeftOutlined />, text: '左对齐' }, // ... 其他工具条配置 { key: 'v-space', icon: <PicCenterOutlined />, text: '垂直分布空间' }, { key: 'h-space', icon: <PicCenterOutlined style={{transform: 'rotate(-90deg)'}} />, text: '水平分布空间' }, ]}
工具条方法封装:
const handleOperate = (key: string) => { // ... some function // 顶对齐实现 if(key === 'top') { const rect = moveableRef.current!.getRect(); // console.log(rect) const moveables = moveableRef.current!.getMoveables(); if (moveables.length <= 1) { return; } moveables.forEach(child => { child.request<DraggableRequestParam>("draggable", { y: rect.top, }, true); }); moveableRef.current?.updateRect(); return } // 底对齐 if(key === 'bottom') { const rect = moveableRef.current!.getRect(); const moveables = moveableRef.current!.getMoveables(); if (moveables.length <= 1) { return; } moveables.forEach(child => { child.request<DraggableRequestParam>("draggable", { y: rect.top + rect.height - (child.props?.target ? (child.props.target as any).offsetHeight : 0), }, true); }); moveableRef.current?.updateRect(); return } // ... 其他工具条方法 // 水平分布 if(key === 'h-space') { const groupRect = moveableRef.current!.getRect(); const moveables = moveableRef.current!.getMoveables(); let left = groupRect.left; if (moveables.length <= 1) { return; } const gap = (groupRect.width - groupRect.children!.reduce((prev, cur) => { return prev + cur.width; }, 0)) / (moveables.length - 1); moveables.sort((a, b) => { return a.state.left - b.state.left; }); moveables.forEach(child => { const rect = child.getRect(); child.request<DraggableRequestParam>("draggable", { x: left, }, true); left += rect.width + gap; }); moveableRef.current?.updateRect(); return } }
通过以上的封装方式我们就能轻松扩展自己的工具条啦~
接下来我们看看工具条实现的效果:
图片
当然代码我已经提交到 github 上了, 大家感兴趣可以参考研究一下。
开源地址:https://github.com/MrXujiang/next-admin
图片
下面直接上代码:
<Selecto ref={selectoRef} // dragCnotallow={container.current} selectableTargets={[".wep-area .cube"]} hitRate={0} selectByClick={true} selectFromInside={false} toggleCnotallow={["shift"]} ratio={0} notallow={e => { const moveable = moveableRef.current!; const target = e.inputEvent.target; const flatted = deepFlat(targets); if ( target.tagName === "BUTTON" || moveable.isMoveableElement(target) || flatted.some(t => t === target || t.contains(target)) ) { e.stop(); } e.data.startTargets = targets; }} notallow={e => { const { startAdded, startRemoved, isDragStartEnd, } = e; if (isDragStartEnd) { return; } const nextChilds = groupManager.selectSameDepthChilds( e.data.startTargets, startAdded, startRemoved, ); setSelectedTargets(nextChilds.targets()); }} notallow={e => { const { isDragStartEnd, isClick, added, removed, inputEvent, } = e; const moveable = moveableRef.current!; if (isDragStartEnd) { inputEvent.preventDefault(); moveable.waitToChangeTarget().then(() => { moveable.dragStart(inputEvent); }); } let nextChilds: TargetList; if (isDragStartEnd || isClick) { if (isCommand) { nextChilds = groupManager.selectSingleChilds(targets, added, removed); } else { nextChilds = groupManager.selectCompletedChilds(targets, added, removed, isShift); } } else { nextChilds = groupManager.selectSameDepthChilds(e.data.startTargets, added, removed); } e.currentTarget.setSelectedTargets(nextChilds.flatten()); setSelectedTargets(nextChilds.targets()); }}></Selecto>
完整代码都同步到 Next-Admin 了, 如果大家感兴趣也可以研究一下。
本文链接://www.dmpip.com//www.dmpip.com/showinfo-26-85858-0.htmlNext-Admin最佳实践!支持可视化拖拽模块
声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com