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 相关文章推荐
JS无法捕获滚动条上的mouse up事件的原因猜想
Mar 21 Javascript
showModalDialog模态对话框的使用详解以及浏览器兼容
Jan 11 Javascript
js实现键盘操作实现div的移动或改变的原理及代码
Jun 23 Javascript
JS中多种方式创建对象详解
Mar 22 Javascript
Restify中接入Socket.io报Error:Can’t set headers的错误解决
Mar 28 Javascript
基于jQuery的表单填充实例
Aug 22 jQuery
详解bootstrap用dropdown-menu实现上下文菜单
Sep 22 Javascript
使用socket.io制做简易WEB聊天室
Jan 02 Javascript
vue 2.x 中axios 封装的get 和post方法
Feb 28 Javascript
js设计模式之代理模式及订阅发布模式实例详解
Aug 15 Javascript
使用Angular material主题定义自己的组件库的配色体系
Sep 04 Javascript
JS实现单张或多张图片持续无缝滚动的示例代码
May 10 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
php空间不支持socket但支持curl时recaptcha的用法
2011/11/07 PHP
PHP中通过HTTP_USER_AGENT判断是否为手机移动终端的函数代码
2013/02/14 PHP
php number_format() 函数通过千位分组来格式化数字的实现代码
2013/08/06 PHP
使用Entrust扩展包在laravel 中实现RBAC的功能
2020/03/16 PHP
js 动态文字滚动的例子
2011/01/17 Javascript
UpdatePanel和Jquery冲突的解决方法
2013/04/01 Javascript
js模拟点击以提交表单为例兼容主流浏览器
2013/11/29 Javascript
angularJS中$apply()方法详解
2015/01/07 Javascript
JavaScript实现Flash炫光波动特效
2015/05/14 Javascript
超赞的动手创建JavaScript框架的详细教程
2015/06/30 Javascript
JS+CSS实现简单滑动门(滑动菜单)效果
2015/09/19 Javascript
详谈js中数组(array)和对象(object)的区别
2017/02/27 Javascript
JS异步文件上传(兼容IE8+)
2017/04/02 Javascript
深入理解node.js之path模块
2017/05/03 Javascript
详解vue express启动数据服务
2017/07/05 Javascript
vee-validate vue 2.0自定义表单验证的实例
2018/08/28 Javascript
零基础之Node.js搭建API服务器的详解
2019/03/08 Javascript
jQuery事件绑定和解绑、事件冒泡与阻止事件冒泡及弹出应用示例
2019/05/13 jQuery
Vue.js中该如何自己维护路由跳转记录
2019/05/19 Javascript
VUE安装使用教程详解
2019/06/03 Javascript
layui数据表格跨行自动合并的例子
2019/09/02 Javascript
vue选项卡切换登录方式小案例
2019/09/27 Javascript
微信小程序后端(java)开发流程的详细步骤
2019/11/13 Javascript
实例讲解JavaScript 计时事件
2020/07/04 Javascript
详解JavaScript之ES5的继承
2020/07/08 Javascript
python编写网页爬虫脚本并实现APScheduler调度
2014/07/28 Python
Python中的复制操作及copy模块中的浅拷贝与深拷贝方法
2016/07/02 Python
CSS3制作皮卡丘动画壁纸的示例
2020/11/02 HTML / CSS
Shopbop中文官网:美国亚马逊旗下时尚购物网站
2020/12/15 全球购物
下面关于"联合"的题目的输出是什么
2013/08/06 面试题
怎样声明一个匿名的内部类
2016/06/01 面试题
学校爱心捐款倡议书
2014/05/13 职场文书
世界文化遗产导游词
2019/08/07 职场文书
tensorflow中的数据类型dtype用法说明
2021/05/26 Python
Java实现简易的分词器功能
2021/06/15 Java/Android
springboot创建的web项目整合Quartz框架的项目实践
2022/06/21 Java/Android