用第三方拖拽库快速撸一个可视化搭建平台

科技趣谈有前端 2024-03-05 08:49:54

之前一直在研究可视化和零代码搭建相关产品和技术, 最近逛 github 的时候发现一个比较有意思的拖拽开源组件, 就用 vue3 简单撸了一个拖拽搭建的小demo, 供大家参考学习.

可视化拖拽demo项目介绍

也是简单设计了几个功能, 如下:

支持设置拖拽单位(阈值)支持撤销重做支持导入和导出 json支持组件全选 / 组合技提供了常用的四个基础组件(文本, 图片, 音频, 视频)

因为之前我的技术栈主要是react, 为了让更多小伙伴低成本的上手, 这里项目采用大家比较熟悉的vue3 + vite.

项目采用的拖拽开源库 es-drager, 当然为了更好的显示代码, 也使用了 monaco-editor, 如下是它的代码展示效果:

image.png

整体来说展示效果还是不错的, 为开源作者们点赞.

完整项目仓库地址: https://github.com/MrXujiang/vue3-drag-demo

一些技术实现的介绍

我之前在社区和公众号也写了很多低代码的技术上实现原理, 如

前端图形学实战: 从零实现编辑器的图层管理面板和实时缩略图(vue3 + vite版)Dooring无代码搭建平台技术演进之路

上面的demo主要实现思路拆解如下:

实现组件从左侧面板拖拽到画布组件在画布中的移动, 操作(全选, 拉伸, 旋转, 参考线等)组件属性的配置可视化的相关操作(导入, 导出, 撤销, 重做等)1.实现组件从左侧面板拖拽到画布

这里实现也很简单, 我们采用H5的原生api: drag & drop 来实现. 也就是说从左侧面板拖拽到画布, 本质上是数据的移动.

2023-12-05 22.10.07.gif

我们先定义好左侧面板的组件类型:

const typeList = reactive(['文本', '图片', '音频', '视频'])

然后再设置拖拽到画布的事件行为:

<div>相关事件:

// 添加function push(type: string) { isupd.value = true; switch (type) { case '文本': data.value.push({ id: uuid(), type: 'text', value: '输入文本', width: 200, height: 50, angle: 0, ...addDistance.value }) reset() break; case '图片': data.value.push({ id: uuid(), type: 'image', value: 'https://turntip.cn/uploads/sucai/11_189dd429f23.webp', width: 100, height: 100, angle: 0, ...addDistance.value }) reset() break; case '音频': data.value.push({ id: uuid(), type: 'audio', value: 'https://turntip.cn/uploads/sucai/Just Relax_189bfc7d990.mp3', width: 300, height: 50, angle: 0, ...addDistance.value }) reset() break; // ... }}

最后在画布上监听拖放事件, 获取“传递的数据”.

// 拖进画布的回调function drop(e: any) { addDistance.value = { top: e.layerY, left: e.layerX } push(addType.value);}

通过这样的操作, 我们就可以将组件从左侧轻松拖拽到画布的指定位置了.

当然实际的低代码设计往往比现在设计的复杂很多, 这里主要是为了方便大家快速理解.

2. 支持组件全选 / 组合

全选和组合实现的思路其实本质上是对数组的操作. 全选的过程中, 我们需要先捕获全选的区域坐标, 然后过滤出这个区域内的组件, 然后批量更新数组中每个选中元素的选中状态:

这里分享一下实现元素组合的逻辑:

// 组合function handleMakeGroup() { const selected = data.value.filter(item => item.selected && item.type != 'combination'); if (selected.length > 1) { let value: any[] = JSON.parse(JSON.stringify(selected)); const Unchecked = data.value.filter(item => !item.selected); const top = selected.sort((x, y) => x.top - y.top)[0].top; const left = selected.sort((x, y) => x.left - y.left)[0].left; const widthArr:number[]=[]; const heightArr:number[]=[] selected.forEach(v=>{ widthArr.push(v.left+v.width-left); heightArr.push(v.top+v.height-top) }) const width=widthArr.sort((x,y)=>y-x)[0]; const height=heightArr.sort((x,y)=>y-x)[0]; value = value.map(v => ({ ...v, top: v.top - top, left: v.left - left })) const obj = { id: uuid(), top, left, width, height, selected: true, value, type: 'combination', angle: 0 } data.value = [...Unchecked, obj] }}

具体实现代码大家可以参考我创建的 github 仓库.

至于其他几个功能比如撤销重做, 导入导出, 都是很基本的操作, 网上也有很多分享, 这里直接上代码:

// 纯前端导入并读取文件function insert({ file, index }: any) { // 创建 FileReader 对象 const reader = new FileReader(); reader.onloadend = function () { data.value[index].value = reader.result; }; // 读取文件并触发 onloadend 事件 reader.readAsDataURL(file);}// 导出文件function download() { const content = editorRef.value.save(); const jsonData = JSON.stringify(content); const downloadLink = document.createElement('a'); downloadLink.setAttribute('href', 'data:text/json;charset=utf-8,' + encodeURIComponent(jsonData)); downloadLink.setAttribute('download', 'data.json'); downloadLink.click(); visible.value = !visible.value;}

当然项目还有很多不足和需要完善的地方, 欢迎大家一起共建.

image.png

完整项目仓库地址: https://github.com/MrXujiang/vue3-drag-demo

线上演示地址: drag_demo 可视化拖拽

后续我也会持续迭代和分享Dooring可视化和低代码的最佳实践, 大家感兴趣的欢迎随时和我交流.

更多推荐
0 阅读:0

科技趣谈有前端

简介:感谢大家的关注