概要
可视化编辑器已成为前端发展趋势,相关产品层出不穷,但是用户较难根据自身需求去完整实现一个功能较为全面的可视化编辑器,我将采用乐吾乐开源的meta2d.js可视化库来实现一个简单的流程图编辑器,通过这个案例来介绍meta2d的相关功能,并向读者展示如何用meta2d从零出发搭建一个较为完整的项目,让我们在实际项目中来体验meta2d的强大之处吧。
什么是乐吾乐meta2d.js
meta2d是乐吾乐开源的2D图元组成的可视化引擎,集实时数据展示、动态交互、数据管理等一体的全功能2D可视化引擎。能够快速实现数字孪生、大屏可视化、Web组态、SCADA等解决方案。具有实时监控、多样、变化、动态交互、高效、可扩展、支持自动算法、跨平台等特点,最大程度减少研发和运维的成本,并致力于普通业务人员 0 代码开发实现物联网、工业互联网、电力能源、水利工程、智慧农业、智慧医疗、智慧城市等可视化解决方案。
乐吾乐已将其meta2d核心库完全免费开源,本系列教程就是基于meta2d从零实现web端可视化流程图编辑器。
乐吾乐 meta2d开源项目地址:https://github.com/le5le-com/meta2d.js
乐吾乐 meta2d官方文档:https://doc.le5le.com/document/119359590
项目地址
此可视化流程图编辑器项目地址:github.com/Grnetsky/me…
在线体验地址: http://editor.xroot.top/
往期教程
- 基本环境搭建: juejin.cn/spost/72617…
- 主界面布局及其初始化: juejin.cn/post/726219…
- Meta2d核心库图元注册流程及相关概念: juejin.cn/spost/72629…
- 侧边栏功能开发:https://juejin.cn/post/7264414580776403003
5. Nav组件功能实现
在这一章我们讲解Nav组件的相关功能实现,就目前的需求来看,需要实现文件的创建保存加载,放大镜、缩略图、钢笔铅笔的功能,其实这些功能的实现都非常简单,基本上都是调用meta2d提供的API即可,接下来让我们来看看这些功能如何实现吧。
保存文件
文件保存的本质就是将画布的数据进行本地储存,存储方式文保存为json文件,meta2d提供了data方法,用于返回画布的相关数据信息返回数据格式json对象,我们只需要将拿到的数据通过浏览器提供的API进行本地保存即可。
在defaultConfig.js中创建saveFile函数,函数内容如下:
saveFile(){
const jsonData = window.meta2d.data() // 获取数据
const json = JSON.stringify(jsonData) // 序列化json对象
const file = new Blob([json],{type:"application/json"}) // 创建文件对象,指定类型为json
const link = URL.createObjectURL(file) // 创建Url指向内存中的文件对象
let a = document.createElement('a') // 创建a标签用于下载操作
a.setAttribute("download","文件名") // 设置download属性 第二个参数为文件名
a.setAttribute("href",link) // 设置a标签的数据来源
a.click() // 点击,开始下载
}
通过meta2d提供的data方法我们可以轻松拿到图纸数据,具体有哪些数据呢?我们来看看官方文档,这些数据统称为Meta2dData数据,表示为meta2d的数据格式,当然这些数据暂时看不懂也没关系,我们只需要知道它提供了一种数据格式用于和meta2d核心库进行交互即可。通过上面方法,最终我们得到了一个json文件,该文件中记录了图纸的所有信息,文件保存的功能就得以实现了。
让我们看看效果:
可以看到数据文件被下载到本地成功,当然,具体文件名可以用一个参数去控制,有需求的可以自己去实现。
加载文件
meta2d提供了open方法用于加载图纸数据,该方法接受两个可选参数,第一个是Meta2dData对象,也就是保存数据时候的带有特定属性的json数据,第二个是布尔值,表示加载完成后是否重新渲染界面,默认为true,当然,你也可以什么参数都不传,他执行的效果就是创建一个新的画布。文件加载到的第一步就是需要拿到文件引用,在浏览器中获取有三种方式,一是通过拖拽,监听drag事件在事件对象中拿到文件引用,二是通过input标签,在回调中拿到文件引用,三是通过挂载到window上的showOpenFilePicker方法,通过异步方式拿到文件引用。前两种方案我们用的特别多,在这里我们尝试一下第三种方式。
async openFile(){
const file = await window.showOpenFilePicker().catch(() => {
console.log("打开文件失败")
return false
})
if (file) {
const dataObj = await file[0].getFile()
const data = await dataObj.text()
if (data) {
const json = JSON.parse(data);
window.meta2d.open(json);
}
}
}
通过showOpenFilePicker方法,就能够打开系统级文件选择器,关于此API的使用,这里不做讨论,有需要的请移步相关文档,该异步方法返回一个句柄数组,该文件句柄数组中包含了所选择的文件引用,通过句柄的getFile方法就能够拿到文件的file对象,通过text方法返回了文件的字符串形式,最终再将字符串进行反序列化生成json对象,该对象就是Meta2dData对象,将该对象传递给meta2d的open方法,最后就成功加载图纸文件了,让我们来看看实际效果。
打开文件的功能也就完成啦,当然,这里只是实现了基本功能,关于该功能的完整细节还有很多事要做,比如打开后是否对上一个图纸进行保存?是否应该清理本地缓存等?这些操作需要结合相关业务需求进行定制,在这里我们只针对该项目更多偏向主要功能的开发。
新建文件
有了前面的基础,新建文件功能就简单多啦,前面说到,meta2d提供了一个open函数用于打开指定文件,但是当不给该函数传参时,就默认新建一个文件,所以在新建功能的开发上,目前只需要调用其open函数即可
newFile(){
window.meta2d.open()
}
来看看实际效果
当然,这里也只是实现了基本功能,具体业务流程和细节,可在后面进行迭代定制。
导入文件
导入文件功能,主要是导入svg类的图元,像之前一样,导入文件前最先要打开文件,然后判断文件类型,类型判断成功则发送给meta2d处理,若不成功就退出提示用户上传正确的格式。文件类型判断主要用file对象的type属性,该属性返回MIME类型,svg的MIME类型为image/svg+xml,当类型通过后调用meta2d通过的parseSvg方法即可。
meta2d提供了缓存机制,meta2d.canvas.addCaches方法用于缓存图元,下次鼠标点击则放置
所以代码像下面这样即可:
async loadFile(){
const file = await window.showOpenFilePicker().catch(() => {
ElMessage({ message: '打开文件失败', type: "error" })
return false
})
if (file) {
//判断文件类型
const dataObj = await file[0].getFile()
console.log()
const data = await dataObj.text()
if (dataObj.type === 'image/svg+xml') {
const pen = parseSvg(data)
meta2d.canvas.addCaches = pen
ElMessage({ message: '添加成功,请点击放置点', type: "success" })
return
}
ElMessage({ message: '添加失败,暂且只支持svg文件', type: "error" })
}
}
接下来看看实际效果吧
放大镜
meta2d核心库内置了放大镜功能,我们只需要调用其api进行放大镜的打开和关闭即可:
- 打开放大镜API:window.meta2d.showMagnifier()
- 关闭放大镜API:window.meta2d.hideMagnifier()
- 查看放大镜状态:window.meta2d.canvas.magnifierCanvas.magnifier (true为打开状态 false为关闭状态)
那我们的函数就很好写了,像下面这样:
openMagnifier(){
if (window.meta2d.canvas.magnifierCanvas.magnifier) { // 判断放大镜状态
window.meta2d.hideMagnifier() // 关闭放大镜
} else {
window.meta2d.showMagnifier() // 打开放大镜
}
}
来看看实际效果
缩略图
与放大镜类似,meta2d也提供了相关api来实现缩略图的显示和隐藏,不过需要注意的是,缩略图对象不像放大镜对象一样是meta2d初始化就创建好的,缩略图需要我们自己调用其show方法才开始创建,所以判断缩略图是否打开之前要判断meta2d身上是否挂载了缩略图,像这样一样
:
openMap(){
if (window.meta2d.map?.isShow) { // 判断缩略图是否已经挂载到meta2d身上,并判断其是否显示
window.meta2d.hideMap() // 隐藏缩略图API
} else {
window.meta2d.showMap() // 显示缩略图API
}
},
当然,你完全可以选择用闭包去做,这样我们的缩略图打开关闭功能就做好了
钢笔
钢笔是meta2d提供的连线工具,meta2d内置了4种连线样式,分别为:
- 直线:line
- 曲线(贝塞尔曲线):curve
- 线段:polyline
默认是曲线,
相关API:
- meta2d.drawLine(LineName):开启指定画线样式的钢笔
- meta2d.drawnLine(): 取消钢笔
- window.meta2d.canvas.drawingLineName:获取钢笔样式,为空则为未使用钢笔
- window.meta2d.finishDrawLine: 钢笔绘画完成
我们可以通过window.meta2d.canvas.drawingLineName身上是否有值来判断钢笔状态,从而调用不同API实现钢笔的打开关闭功能,像下面代码一样:
usePen(){
if (window.meta2d.canvas.drawingLineName) { // 判断是否正在使用钢笔
window.meta2d.drawLine() // 参数为空 取消钢笔
window.meta2d.finishPencil() // 绘画完成
} else {
window.meta2d.drawLine('curve') // 使用钢笔 线条属性为curve
}
}
同样的你完全也可以用闭包来实现,像下面这样:
usePen: (() => {
let flat = false
return () => {
if (!flat) {
window.meta2d.drawLine('curve')
} else {
window.meta2d.drawLine()
window.meta2d.finishPencil() // 绘画完成
}
flat = !flat
}
})(),
效果图如下:
铅笔
与钢笔功能类似,铅笔是用来生成任意路径的工具,我们来看看官方提供了些什么API吧:
- meta2d.drawingPencil():开启铅笔
- meta2d.stopPencil():停止绘画
- meta2d.finishPencil():绘画完成
- meta2d.canvas.pencil: 当前pencil状态
一眼就知道该怎么做了吧,和上面一样:
usePencil(){
if (window.meta2d.canvas.pencil) {
window.meta2d.stopPencil()
window.meta2d.finishPencil()
} else {
window.meta2d.drawingPencil()
}
}
看看效果吧
总结
通过这章,我们学习到了一些nav组件基本功能的实现,核心还是调用meta2d提供的相关api,最好参考官方文档来做,在后面章节,我们可以尝试增加更多功能增加工具栏等,敬请期待~
Meta2d.js 开源地址
给大家推荐一下 Meta2d.js是一个实时数据响应和交互的2d引擎,可用于Web组态,物联网,数字孪生等场景。
Github:https://github.com/le5le-com/meta2d.js
Gitee: https://gitee.com/le5le/meta2d.js
大家一起去为这个国产的开源产品star一下吧,毕竟优秀的国产可视化开源项目不多。