之前一直在研讨可视化和零代码建立相关产品和技能, 最近逛 github
的时候发现一个比较有意思的拖拽开源组件, 就用 vue3
简略撸了一个拖拽建立的小demo, 供咱们参阅学习.
可视化拖拽demo项目介绍
也是简略设计了几个功用, 如下:
- 支撑设置拖拽单位(阈值)
- 支撑撤销重做
- 支撑导入和导出 json
- 支撑组件全选 / 组合
- 技提供了常用的四个根底组件(文本, 图片, 音频, 视频)
因为之前我的技能栈首要是react
, 为了让更多小伙伴低成本的上手, 这儿项目选用咱们比较了解的vue3 + vite
.
项目选用的拖拽开源库 es-drager
, 当然为了更好的显示代码, 也使用了 monaco-editor
, 如下是它的代码展现作用:
全体来说展现作用仍是不错的, 为开源作者们点赞.
完好项目库房地址: github.com/MrXujiang/v…
线上演示地址: drag_demo 可视化拖拽
一些技能完成的介绍
我之前在社区和公众号也写了许多低代码的技能上完成原理, 如
上面的demo首要完成思路拆解如下:
- 完成组件从左边面板拖拽到画布
- 组件在画布中的移动, 操作(全选, 拉伸, 旋转, 参阅线等)
- 组件特点的配置
- 可视化的相关操作(导入, 导出, 撤销, 重做等)
1.完成组件从左边面板拖拽到画布
这儿完成也很简略, 咱们选用H5的原生api: drag & drop 来完成. 也就是说从左边面板拖拽到画布, 本质上是数据的移动.
咱们先定义好左边面板的组件类型:
const typeList = reactive(['文本', '图片', '音频', '视频'])
然后再设置拖拽到画布的事情行为:
<div class="menu">
<div
v-for="item in typeList"
@click="push(item)"
:draggable="true"
@dragstart="addType = item"
>
{{ item }}
</div>
</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://www.6hu.cc/wp-content/uploads/2023/12/224902-zcnWiy.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;
}
当然项目还有许多不足和需求完善的地方, 欢迎咱们一同共建.
完好项目库房地址: github.com/MrXujiang/v…
线上演示地址: drag_demo 可视化拖拽
后续我也会持续迭代和共享Dooring可视化和低代码的最佳实践, 咱们感兴趣的欢迎随时和我交流.