欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

GOJS+VUE实现流程图效果

程序员文章站 2022-03-04 13:41:03
前言及展示 在项目中需要根据传过来的数据画出流程图,采用了gojs插件,功能很全面,可以根据自己的需要调整,不过建议简单的流程图还是自己手写一个组件,更加便于维护和变换。...

前言及展示

在项目中需要根据传过来的数据画出流程图,采用了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" } 
 ];

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