Bootstrap

基于乐吾乐meta2d从零实现可视化流程图编辑器(十二)

概要

可视化编辑器已成为前端发展趋势,相关产品层出不穷,但是用户较难根据自身需求去完整实现一个功能较为全面的可视化编辑器,我将采用乐吾乐开源的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/

往期教程

  1. 基本环境搭建: juejin.cn/spost/72617…
  2. 主界面布局及其初始化: juejin.cn/post/726219…
  3. Meta2d核心库图元注册流程及相关概念: juejin.cn/spost/72629…
  4. 侧边栏功能开发:https://juejin.cn/post/7264414580776403003
  5. Nav组件功能实现:https://juejin.cn/post/7264951443344916517
  6. Nav组件扩展-添加工具栏:https://juejin.cn/post/7265692989611147283
  7. setting组件框架搭建及其Map组件实现:https://juejin.cn/post/7267418197728116748
  8. 引入自定义图元库详解:https://juejin.cn/post/7267948449966096447
  9. Global全局配置组件实现:https://juejin.cn/post/7269349453588660260
  10. 初识PenProps及其Appearance组件实现: https://juejin.cn/post/7270140695477387319
  11. meta2d事件消息及Event组件实现:https://juejin.cn/post/7271120191005392931

12.图元动效与动效组件实现

虽然本项目对动画效果基本没有需求,但是考虑到动画效果是大多读者可能都会关心的内容,所以在这进行简单的介绍,如果本章内容对你有帮助,欢迎给meta2d 点星。

图元动效

meta2d提供了节点的动画效果,可以参考官方文档,从官网可以了解到,meta2d的动画分为两种,一种是节点动画,一种在连线动画,由于本项目不涉及复杂的连线动画,这里我们只简单讨论节点动画,节点动画属于帧动画,逐帧执行。主要由:帧时长 + 变化属性 2 部分组成,meta2d的图元上有frames属性,用于保存节点动画的帧动画列表,用官网的例子来解释:

// frames指向帧动列表
pen.frames = [
  {
    duration: 1000,  // 帧时长
    rotate: 20,    // 变化属性
  },    
  // 下一帧动画
  {
    duration: 2000,
    rotate: -20,
  },
];

可以看到该frames属性上绑定了两个帧动画,他会在发出执行动画命令后依次执行。我们再来看看关于动画有哪些命令:

  • meta2d.startAnimate():执行动画,参数为目标图元的id,当执行多个图元的动画时,参数可为tag和 [ pens ] 图元列表.
  • meta2d.pauseAnimate(): 暂停动画,参数如上
  • meta2d.stopAnimate():停止动画,参数同上

注意,这些都是meta2d身上的属性,并非图元属性

我们再来看看关于动画的其他属性:

  • pen.animateCycle(): 该方法用于指定动画循环次数,默认为Infinity,即无限次。
  • pen.keepAnimateState:该属性用于指定动画结束后是否回到初始状态,默认true。
  • pen.autoPlay:该属性用于设置图元是否加载后自动播放动画,默认false。
  • pen.nextAnimate:该属性用于设置此图元动画结束后紧接着下个播放动画的图元的id。

在实际开发中我们只需要根据自己的需求来调用相关api就行了,接下来,我们在此基础上实现我们的Animate组件,向用户暴露接口给图元设置动画。

Animate组件实现

Animate组件用于让用户给图元设置动画效果,我们应该给用户一些预设选项,meta2d原生并未提供相关内容,需要我们自行完成对动画的设计,在defaultConfig中配置frames预设项,考虑到为教学内容,所以就不做太复杂的动画了

// defaultConfig.js
export const animateType = [
  {
      name:"跳动",
      key:"bounce",
      frames:[
          {
              duration: 300,
              y:10
          },
      ]
  },
  {
      name:"旋转",
      key:"rotate",
      frames: [
          {
              duration:1000,
              rotate:360
          },

      ]
  },
  {
      name:"提示",
      key:"tip",
      frames: [{
          duration:300,
          scale:1.3
      }]
  }
]

然后我们需要将它在界面渲染出来,模板代码如下:

// Animate.vue
<template>
<div class="animate">
  <el-form @submit="(e)=>e.preventDefault()">
    <el-form-item label="动画类型" >
      <el-select v-model="animate.frames" value-key="id" placeholder="选择事件类型" @change="changeAnimate">
        <el-option
            v-for="e in m"
            :key="e.key"
            :label="e.name"
            :value="e.frames"
        >
        </el-option>
      </el-select>
    </el-form-item>

    <el-form-item label="动画时长" >
      <el-input v-model="animate.duration" disabled/>

    </el-form-item>

    <el-form-item label="自动播放" >
      <el-switch v-model="animate.autoPlay"/>

    </el-form-item>
    <div class="event_button">
      <el-button @click="startAnimate" type="primary" style="width: 60px;font-size: 10px">开始动画</el-button>
      <el-button @click="pauseAnimate" type="danger" style="width: 60px;font-size:10px">暂停动画</el-button>
      <el-button @click="stopAnimate" type="danger" style="width: 60px;font-size:10px">停止动画</el-button>
    </div>
  </el-form>
</div>
</template>

动画类型输入框用于对动画的选择,动画时长向用户反馈此动画执行需要多少时长,自动播放与pen的autoPlay属性对应,然后底部三个按钮,用于控制动画的开始、暂停和停止操作,我们在来看看相关逻辑函数怎么写:

<script setup>
import {animateType} from "../../data/defaultsConfig.js";
import {onMounted, reactive, ref, toRaw} from "vue";

let m = reactive(animateType)
let animate = ref({  // 动画对象
  name:"",
  frames:[],
  key:"",
  duration:0,
  autoPlay:false,
  animateCycle:Infinity
})

let activePen = {}  // 当前激活的图元

onMounted(()=>{
  meta2d.on('active',(pens)=>{ // 监听系统事件获取当前激活图元
    animate.value = {
      name:"",
      frames:[],
      key:"",
      duration:0,
      autoPlay:false,
      animateCycle:Infinity
    }
    if(pens.length === 1){
      activePen = reactive(pens[0])
    }
    if(pens[0]){  // 图元动画效果回显
      animate.value.autoPlay = activePen.autoPlay ||false
      animate.value.animateCycle = activePen.animateCycle || Infinity
      animate.value.frames = activePen.frames || []
      animate.value.name = activePen.animateName || ''
      animate.value.duration = activePen.animateDuration || 0
    }

  })
})

// 设置图元动画
function changeAnimate(f){
  animate.value.duration = f[0].duration
}

// 开始执行动画
function startAnimate(){
  activePen.animateName = animate.value.name
  activePen.animateDuration = animate.value.frames[0].duration
  activePen.frames = animate.value.frames
  activePen.autoPlay = animate.value.autoPlay
  activePen.animateCycle = animate.value.animateCycle
  meta2d.startAnimate(activePen.id)
}

// 暂停动画
function pauseAnimate() {
  meta2d.pauseAnimate(activePen.id)
}

// 停止动画
function stopAnimate() {
  meta2d.stopAnimate(activePen.id)
}

有了前面的事件的基础后,我相信这很好理解,根据用户选择的animateType预设将对应的frames赋值给图元即可,然后根据不同按钮执行meta2d提供的相关API,对于回显我们需要监听active事件,然后在回调中进行相关属性的重新赋值即可,若没有相关属性则赋值为初始化数据,来看看实现的效果吧。

animate2 000000000030gif

总结

本章我们对meta2d的帧动画效果进行了简单的讲解并实现了Animate组件,我们能够用其去给图元配置简单的动画,在实际开发过程中,最重要的是如何去设计动画,需要读者发挥自己的创造力利用meta2d的帧动画相关API去实现效果,在下一章,我们将讲解我们整个项目的最后一个部分contextMenu右键菜单,下章见。

有问题欢迎在评论区反馈,欢迎持续关注。

Meta2d.js 开源地址

给大家推荐一下 Meta2d.js是一个实时数据响应和交互的2d引擎,可用于Web组态,物联网,数字孪生等场景。

Github:github.com/le5le-com/m…

Gitee: gitee.com/le5le/meta2…

如果本篇文章帮助到了你,欢迎为meta2d项目star点星。

;