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 相关文章推荐
JQuery扩展插件Validate 5添加自定义验证方法
Sep 05 Javascript
用js替换除数字与逗号以外的所有字符的代码
Jun 07 Javascript
jquery树形菜单效果的简单实例
Jun 06 Javascript
Bootstrap基本组件学习笔记之input输入框组(9)
Dec 07 Javascript
Angular2中select用法之设置默认值与事件详解
May 07 Javascript
详解webpack的配置文件entry与output
Aug 21 Javascript
详解RequireJs官方使用教程
Oct 31 Javascript
webpack打包js文件及部署的实现方法
Dec 18 Javascript
vue中element-ui表格缩略图悬浮放大功能的实例代码
Jun 26 Javascript
深入理解Angularjs 脏值检测
Oct 12 Javascript
Fundebug支持监控微信小程序HTTP请求错误的方法
Feb 21 Javascript
微信小程序间使用navigator跳转传值问题实例分析
Mar 27 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
关于拼配咖啡,你要知道
2021/03/03 咖啡文化
PHP中for与foreach的区别分析
2011/03/09 PHP
浅谈Laravel中的三种中间件的作用
2019/10/13 PHP
关于捕获用户何时点击window.onbeforeunload的取消事件
2011/03/06 Javascript
JQuery中$.ajax()方法参数详解及应用
2013/12/12 Javascript
解决checkbox的attr(checked)一直为undefined问题
2014/06/16 Javascript
Shell脚本实现Linux系统和进程资源监控
2015/03/05 Javascript
微信小程序 实战实例开发流程详细介绍
2017/01/05 Javascript
JavaScript严格模式详解
2017/01/16 Javascript
Vuex模块化实现待办事项的状态管理
2017/03/15 Javascript
JQuery EasyUI的一些常用组件
2017/07/12 jQuery
浅谈React中组件间抽象
2018/01/27 Javascript
JavaScript实现小球沿正弦曲线运动
2020/09/07 Javascript
electron-vue利用webpack打包实现多页面的入口文件问题
2019/05/12 Javascript
js+HTML5 canvas 实现简单的加载条(进度条)功能示例
2019/07/16 Javascript
移动端吸顶fixbar的解决方案详解
2019/07/17 Javascript
微信小程序中的上拉、下拉菜单功能
2020/03/13 Javascript
pycharm 使用心得(九)解决No Python interpreter selected的问题
2014/06/06 Python
python实现的一个火车票转让信息采集器
2014/07/09 Python
Python(TensorFlow框架)实现手写数字识别系统的方法
2018/05/29 Python
Python数据类型之Dict字典实例详解
2019/05/07 Python
django数据模型(Model)的字段类型解析
2019/12/25 Python
Python内置类型性能分析过程实例
2020/01/29 Python
Python表达式的优先级详解
2020/02/18 Python
python 子类调用父类的构造函数实例
2020/03/12 Python
python数据类型强制转换实例详解
2020/06/22 Python
Python预测2020高考分数和录取情况
2020/07/08 Python
Canvas高级路径操作之拖拽对象的实现
2019/08/05 HTML / CSS
英国轻奢珠宝品牌:Astley Clarke
2016/12/18 全球购物
旅游管理毕业生自荐信
2013/11/05 职场文书
体育教师自我鉴定
2014/02/12 职场文书
师德模范事迹材料
2014/06/03 职场文书
学雷锋活动倡议书
2014/08/30 职场文书
土建技术员岗位职责
2015/04/11 职场文书
选购到合适的激光打印机
2022/04/21 数码科技
MySQL 原理与优化之原数据锁的应用
2022/08/14 MySQL