GOJS+VUE实现流程图效果


Posted in Javascript onDecember 01, 2018

前言及展示

在项目中需要根据传过来的数据画出流程图,采用了GOJS插件,功能很全面,可以根据自己的需要调整,不过建议简单的流程图还是自己手写一个组件,更加便于维护和变换。有一点需要注意的是,GOJS是需要收费的,有水印,虽然可以手动去掉,但是公司用的话还是需要买。GOJS的官网上有关于在VUE中应用GOJS的小例子:Minimal GoJS Sample in Vue.js。推荐看一下,可以解决大部分简单需求,这个例子可以满足你并行步骤数比较固定的二叉树画法的流程图。

GOJS+VUE实现流程图效果

这是官网的例子,其中模块,线,箭头等画布元素都可以交互。
由于我的并行步骤数不固定,于是在图中加入了Group(组)。先展示一下成品:

GOJS+VUE实现流程图效果

其中批次中可以包含多个项目,表示并行的步骤。

具体实现

分为两个文件:
diagram.vue && stepMap.vue
diagram.vue声明组件,stepMap引用

diagram.vue

基本声明:

<script>
 import go from 'gojs';
 let $ = go.GraphObject.make; // 后面很多用到该变量来初始化diagram
 export default{
  name: 'diagram',
  props: ['modelData'], // accept model data as a parameter
  data() {
   return {
   diagram: null,
   }; 
  }, // provide access to the GoJS Diagram

初始化diagram:

mounted: function() {
  let self = this;
  let myDiagram =
   $(go.Diagram, this.$el,
   {
    'initialContentAlignment': go.Spot.Center,
    'isEnabled': false, // 是否可拖拽,默认为是
    // 'toolManager.mouseWheelBehavior': go.ToolManager.WheelNone,
    'allowLink': false, 
    'allowMove': false,
    'allowRelink': false, // 由于项目只想展示数据,我禁用了大部分图像交互操作,具体可参看官网API
    'layout': $(go.TreeLayout, {angle: 0, arrangement: go.TreeLayout.ArrangementHorizontal}),  // angle可控制图像展示方向
    'undoManager.isEnabled': true,
    // Model ChangedEvents get passed up to component users
    'ChangedSelection': function(e) {
     self.$emit('changed-selection', e); 
    },
   });
   
  myDiagram.nodeTemplate = // 节点的初始化设置
   $(go.Node, 'Auto',
   $(go.Shape, // 节点形状设置
   {
    fill: 'white', strokeWidth: 1,
    portId: '', fromLinkable: true, toLinkable: true, cursor: 'pointer',
   },
    new go.Binding('fill', '', this.nodeColorConverter)), // nodeColorConverter是我自定义函数,根据节点状态设置节点的背景颜色
   $(go.TextBlock, // 节点提示文字设置
    {margin: 16, editable: false},
    new go.Binding('text').makeTwoWay())
   );

  myDiagram.linkTemplate =
   $(go.Link,
   {relinkableFrom: true, relinkableTo: true},
   $(go.Shape, // 连线形状设置
   {strokeWidth: 2},
   new go.Binding('stroke', '', this.linkColorConverter)), // 连线的颜色设置
   $(go.Shape, // arrowhead
   {toArrow: 'Triangle', stroke: null, scale: 1.5}, // 箭头设置
   new go.Binding('fill', '', this.linkColorConverter))
   );
  
  myDiagram.groupTemplate = // 分组的初始化
   $(go.Group, 'Auto',
    { // define the group's internal layout
    layout: $(go.TreeLayout,
       {angle: 90, arrangement: go.TreeLayout.ArrangementVertical, isRealtime: false}),
    // the group begins unexpanded;
    // upon expansion, a Diagram Listener will generate contents for the group
    // when a group is expanded, if it contains no parts, generate a subGraph inside of it
    // subGraphExpandedChanged: function(group) {
    // if (group.memberParts.count === 0) {
    //  randomGroup(group.data.key);
    // }
    // },
    },
   $(go.Shape, 'Rectangle',
    {fill: null, stroke: 'gray', strokeWidth: 2}),
   $(go.Panel, 'Vertical',
    {defaultAlignment: go.Spot.Left, margin: 4},
    $(go.Panel, 'Horizontal',
    {defaultAlignment: go.Spot.Top},
    $('SubGraphExpanderButton', {alignment: go.Spot.Top, margin: 5}),
    // the SubGraphExpanderButton is a panel that functions as a button to expand or collapse the subGraph
    $(go.TextBlock,
     {
     font: 'Bold 14px Sans-Serif',
     margin: 10,
     },
     new go.Binding('text', 'text'))
    ),
   // create a placeholder to represent the area where the contents of the group are
    $(go.Placeholder,
    {padding: new go.Margin(0, 10)}),
   ) // end Vertical Panel
   ); // end Group

   // generate the initial model
  this.diagram = myDiagram;
  this.updateModel(this.modelData);

更新图中数据时需要的函数:

watch: {
  modelData: function(val) { 
   this.updateModel(val); 
  },
  },
  methods: {
  model: function() { 
   return this.diagram.model; 
  },
  updateModel: function(val) {
   // No GoJS transaction permitted when replacing Diagram.model.
   if (val instanceof go.Model) {
   this.diagram.model = val;
   } else {
   let m = new go.GraphLinksModel();
   if (val) {
    for (let p in val) {
    if (val[p]) {
     m[p] = val[p];
    }
    }
   }
   this.diagram.model = m;
   }
  },
  updateDiagramFromData: function() {
   this.diagram.startTransaction();
   // This is very general but very inefficient.
   // It would be better to modify the diagramData data by calling
   // Model.setDataProperty or Model.addNodeData, et al.
   this.diagram.updateAllRelationshipsFromData();
   this.diagram.updateAllTargetBindings();
   this.diagram.commitTransaction('updated');
  },
  },
 };
</script>

声明后在stepMap调用,比较重要的是这两个方法:

updateDiagramFromData: function() {
   this.$refs.diag.updateDiagramFromData(); // 数据变化时调用组件中的更新方法
  },
changedSelection: function(e) {
   let node = e.diagram.selection.first();
   if (node instanceof go.Node) {
   this.currentNode = node;
   this.currentNodeText = node.data.text;
   this.selectNode(node.data);
   } else {
   this.currentNode = null;
   this.currentNodeText = '';
   }
  },

最后,将需要展示的数据转化为需要的格式就可以啦。

流程图所需格式如下:

无分组:
 "nodeDataArray": [ 
{"key":1, "text":"Alpha", "color":"lightblue"},
{"key":2, "text":"Beta", "color":"orange"},
{"key":3, "text":"Gamma", "color":"lightgreen"},
{"key":4, "text":"Delta", "color":"pink"}
 ]
 "linkDataArray": [ 
{"from":1, "to":2},
{"from":1, "to":3},
{"from":3, "to":4}
 ]
有分组:
 var nodeDataArray = [
 { key: "Alpha" },
 { key: "Beta", group: "Omega" },
 { key: "Gamma", group: "Omega" },
 { key: "Omega", isGroup: true }, 
 { key: "Delta" }
 ];
 var linkDataArray = [
 { from: "Alpha", to: "Beta" }, 
 { from: "Beta", to: "Gamma" }, 
 { from: "Omega", to: "Delta" } 
 ];

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
实现复选框全选/全不选切换
Dec 23 Javascript
jquery禁用右键示例
Apr 28 Javascript
浅谈EasyUI中编辑treegrid的方法
Mar 01 Javascript
基于javascript实现漂亮的页面过渡动画效果附源码下载
Oct 26 Javascript
基于javascript实现图片左右切换效果
Jan 25 Javascript
Bootstrap中文本框的宽度变窄并且加入一副验证码图片的实现方法
Jun 23 Javascript
JS 实现计算器详解及实例代码(一)
Jan 08 Javascript
php简单数据库操作类的封装
Jun 08 Javascript
Vue2.0基于vue-cli+webpack Vuex的用法(实例讲解)
Sep 15 Javascript
禁止弹窗中蒙层底部页面跟随滚动的几种方法
Dec 07 Javascript
vue路由拦截及页面跳转的设置方法
May 24 Javascript
vue数据更新UI不刷新显示的解决办法
Aug 06 Javascript
JavaScript实现简单轮播图效果
Dec 01 #Javascript
jQuery-ui插件sortable实现自由拖动排序
Dec 01 #jQuery
jquery拖拽自动排序插件使用方法详解
Jul 20 #jQuery
vue实现移动端悬浮窗效果
Dec 01 #Javascript
vue拖拽组件使用方法详解
Dec 01 #Javascript
vue实现div拖拽互换位置
Jul 29 #Javascript
vue插件draggable实现拖拽移动图片顺序
Dec 01 #Javascript
You might like
用js实现预览待上传的本地图片
2007/03/15 Javascript
让JavaScript拥有类似Lambda表达式编程能力的方法
2010/09/12 Javascript
jquery validate和jquery form 插件组合实现验证表单后AJAX提交
2015/08/26 Javascript
javascript随机抽取0-100之间不重复的10个数
2016/02/25 Javascript
D3.js实现散点图和气泡图的方法详解
2016/09/21 Javascript
微信小程序 简单DEMO布局,逻辑,样式的练习
2016/11/30 Javascript
总结js函数相关知识点
2018/02/27 Javascript
JavaScript简单实现动态改变HTML内容的方法示例
2018/12/25 Javascript
使用vuex解决刷新页面state数据消失的问题记录
2019/05/08 Javascript
微信小程序非跳转式组件授权登录的方法示例
2019/05/22 Javascript
VsCode与Node.js知识点详解
2019/09/05 Javascript
layui默认选中table的CheckBox复选框方法
2019/09/19 Javascript
vue中使用rem布局代码详解
2019/10/30 Javascript
一篇文章带你从零快速上手Rollup
2020/09/07 Javascript
[01:46]新英雄登场
2019/09/10 DOTA
Python getopt模块处理命令行选项实例
2014/05/13 Python
Python3中多线程编程的队列运作示例
2015/04/16 Python
Python实现类的创建与使用方法示例
2017/07/25 Python
python+opencv实现霍夫变换检测直线
2020/10/23 Python
Django中如何防范CSRF跨站点请求伪造攻击的实现
2019/04/28 Python
python实现计算器功能
2019/10/31 Python
Python 识别12306图片验证码物品的实现示例
2020/01/20 Python
python使用梯度下降和牛顿法寻找Rosenbrock函数最小值实例
2020/04/02 Python
python 使用tkinter+you-get实现视频下载器
2020/11/17 Python
python实现定时发送邮件到指定邮箱
2020/12/23 Python
借助HTML5 Canvas来绘制三角形和矩形等多边形的方法
2016/03/14 HTML / CSS
Bose英国官方网站:美国知名音响品牌
2020/01/26 全球购物
小学新教师培训方案
2014/02/03 职场文书
一句话工作感言
2014/03/01 职场文书
2014两会学习心得:榜样精神伴我行
2014/03/17 职场文书
中国梦我的梦演讲稿
2014/04/23 职场文书
2014群众路线学习笔记
2014/11/06 职场文书
先进单位事迹材料
2014/12/25 职场文书
python tqdm用法及实例详解
2021/06/16 Python
idea搭建可运行Servlet的Web项目
2021/06/26 Java/Android
Pygame Time时间控制的具体使用详解
2021/11/17 Python