GOJS+VUE实现流程图效果
程序员文章站
2022-03-04 13:41:03
前言及展示
在项目中需要根据传过来的数据画出流程图,采用了gojs插件,功能很全面,可以根据自己的需要调整,不过建议简单的流程图还是自己手写一个组件,更加便于维护和变换。...
前言及展示
在项目中需要根据传过来的数据画出流程图,采用了gojs插件,功能很全面,可以根据自己的需要调整,不过建议简单的流程图还是自己手写一个组件,更加便于维护和变换。有一点需要注意的是,gojs是需要收费的,有水印,虽然可以手动去掉,但是公司用的话还是需要买。gojs的官网上有关于在vue中应用gojs的小例子:minimal gojs sample in vue.js。推荐看一下,可以解决大部分简单需求,这个例子可以满足你并行步骤数比较固定的二叉树画法的流程图。
这是官网的例子,其中模块,线,箭头等画布元素都可以交互。
由于我的并行步骤数不固定,于是在图中加入了group(组)。先展示一下成品:
其中批次中可以包含多个项目,表示并行的步骤。
具体实现
分为两个文件:
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" } ];
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 一定要让你搞懂Java位运算符
下一篇: koa2实现登录注册功能的示例代码