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 相关文章推荐
javascript十六进制及二进制转化的方法
May 06 Javascript
jQuery实现在最后一个元素之前插入新元素的方法
Jul 18 Javascript
[原创]JQuery 在表单提交之前修改 提交的值
Apr 14 Javascript
全面接触神奇的Bootstrap导航条实战篇
Aug 01 Javascript
JQuery遍历元素的后代和同胞实现方法
Sep 18 Javascript
一篇文章让你彻底弄懂JS的事件冒泡和事件捕获
Aug 14 Javascript
vuejs项目打包之后的首屏加载优化及打包之后出现的问题
Apr 01 Javascript
vue.js响应式原理解析与实现
Jun 22 Javascript
jquery简单实现纵向的无缝滚动代码实例
Apr 01 jQuery
vuex实现像调用模板方法一样调用Mutations方法
Nov 06 Javascript
浅谈JavaScript中this的指向问题
Jul 28 Javascript
微信小程序中data-key属性之数据传输(经验总结)
Aug 22 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
SONY SRF-M100的电路分析
2021/03/02 无线电
比较好用的PHP防注入漏洞过滤函数代码
2012/04/11 PHP
使用php实现下载生成某链接快捷方式的解决方法
2013/05/07 PHP
PHP上传文件时文件过大$_FILES为空的解决方法
2013/11/26 PHP
php curl模拟post提交数据示例
2013/12/31 PHP
PHP实现的通过参数生成MYSQL语句类完整实例
2016/04/11 PHP
PHP 匿名函数与注意事项详细介绍
2016/11/26 PHP
PHP实现十进制、二进制、八进制和十六进制转换相关函数用法分析
2017/04/25 PHP
PHP优化之批量操作MySQL实例分析
2020/04/23 PHP
jQuery学习总结之元素的相对定位和选择器(持续更新)
2011/04/26 Javascript
jquery easyui combobox模糊过滤(示例代码)
2013/11/30 Javascript
Node.JS中事件轮询(Event Loop)的解析
2017/02/25 Javascript
图解Javascript——作用域、作用域链、闭包
2017/03/21 Javascript
iscroll实现下拉刷新功能
2017/07/18 Javascript
详解ES6中的代理模式——Proxy
2018/01/08 Javascript
inquirer.js一个用户与命令行交互的工具详解
2019/05/18 Javascript
vue 开发企业微信整合案例分析
2019/12/02 Javascript
python实现将汉字转换成汉语拼音的库
2015/05/05 Python
实例讲解Python中函数的调用与定义
2016/03/14 Python
在python中实现对list求和及求积
2018/11/14 Python
对python pandas 画移动平均线的方法详解
2018/11/28 Python
Python模块 _winreg操作注册表
2020/02/05 Python
python自动脚本的pyautogui入门学习
2020/04/01 Python
pandas中的ExcelWriter和ExcelFile的实现方法
2020/04/24 Python
HTML5 播放 RTSP 视频的实例代码
2019/07/29 HTML / CSS
html5 canvas实现给图片添加平铺水印
2019/08/20 HTML / CSS
软件测试企业面试试卷
2016/07/13 面试题
客服专员岗位职责范本
2013/11/29 职场文书
医学生自荐信
2013/12/03 职场文书
西柏坡导游词
2015/02/05 职场文书
2015年大学迎新晚会总结
2015/07/16 职场文书
基于python实现银行管理系统
2021/04/20 Python
Mysql8.0递归查询的简单用法示例
2021/08/04 MySQL
Python anaconda安装库命令详解
2021/10/16 Python
mysql分组后合并显示一个字段的多条数据方式
2022/01/22 MySQL
漫画「处刑少女的生存之道」第3卷封面公开
2022/03/21 日漫