首页 > 编程 > JavaScript > 正文

vue中使用gojs/jointjs的示例代码

2019-11-19 13:09:57
字体:
来源:转载
供稿:网友

因为公司项目需求,要画出相关业务的流程图,以便客户了解自己身处何处

搜索框输入 “前端流程图插件”,查了很多资料,总结一下有以下几种

flow-chart

代码写法繁琐,不是json就可以解决,效果也比较丑,PASS

darge-d3

github :https://github.com/dagrejs/dagre-d3

效果图

下载里面的demo,改一下json就可以了

// States var states = [ "NEW", "SUBMITTED","FINISHED" ,"FAILED","DELIVER",     "CANCELED", "ABOLISHED" , "DELETED","REFUNDING","REFUNDED"];var map = ['新创建','已提交','已完成','提交失败',"交付中",    '已取消','废除','已删除','退款中',"已退款"]// Automatically label each of the nodesstates.forEach(function(state,index) { g.setNode(state, { label: `${map[index]}(${state})`})});// Set up the edgesg.setEdge("NEW", "FAILED",  { label: "后台接口自动"});g.setEdge("NEW", "SUBMITTED", { label: "后台接口自动" });g.setEdge("NEW", "CANCELED", { label: "用户取消订单" });g.setEdge("SUBMITTED","CANCELED",  { label: "用户取消订单" });g.setEdge("SUBMITTED", "ABOLISHED", { label: "用户超过48小时未支付,/n系统自动取消"});g.setEdge("ABOLISHED","DELETED",  { label: "已删除" });g.setEdge("CANCELED", "DELETED", { label: "已删除"});g.setEdge("FAILED", "SUBMITTED",  { label: "后台接口自动" });g.setEdge("SUBMITTED", "DELIVER",  { label: "用户支付" });g.setEdge("FINISHED", "REFUNDING",  { label: "用户退款" });g.setEdge("DELIVER", "FINISHED",  { label: "交付完成" });g.setEdge("REFUNDING", "REFUNDED",  { label: "已退款" });g.setEdge("REFUNDED", "DELETED",  { label: "已删除" });g.setEdge("DELIVER", "REFUNDING",  { label: "用户退款" });g.setEdge("FAILED", "CANCELED",  { label: "用户取消订单" });

不满意的地方:画出来的图是垂直方向的,我要的是水平方向,PASS

gojs

GoJS是一个实现交互类图表(比如流程图,树图,关系图,力导图等等)的JS库。本文将介绍GoJs的精华部分。
因为GoJS依赖于HTML5,所以请保证您的浏览器版本支持HTML5,当然还要加载这个库。

github :https://github.com/NorthwoodsSoftware/GoJS

可以通过npm install gojs -save安装

效果图

看里面的demo我自己包装了一下

<template><div> <p style="background-color:#d5d5d5;margin:0;padding:5px;"> 您当前处于 <span class="tip">用户提交资料</span> 步骤  下一步等待<span class="tip">供应商接单</span> <el-button type="text" v-if="show===false" @click="show=true">展开</el-button> <el-button type="text" v-else @click="show=false">收起</el-button>  </p> <div id="myDiagramDiv" v-show="show" ></div> </div>  </template><style scoped>.tip{ color:red; font-size:0.8em; font-weight:bold; padding:5px;}#myDiagramDiv{ height: 200px;  border: solid 1px #d3d3d3;}</style>
<script>window.go =require('./go.js') var $ = go.GraphObject.make;import datam from './data';export default{ mixins:[datam], data(){ return{  myDiagram:null,  show:true } }, mounted(){ this.load(); }, methods:{ load(){  this.init();  this.addNodeTemplate(this.User);  this.addNodeTemplate(this.Supplier);  this.layout(); }, layout() {  this.myDiagram.model = go.Model.fromJson(this.myjson);  this.myDiagram.layoutDiagram(true); }, getOption(){  // for conciseness in defining templates  let options={  yellowgrad : $(go.Brush, "Linear", { 0: "rgb(254, 201, 0)", 1: "rgb(254, 162, 0)" }),  greengrad : $(go.Brush, "Linear", { 0: "#98FB98", 1: "#9ACD32" }),  bluegrad : $(go.Brush, "Linear", { 0: "#B0E0E6", 1: "#87CEEB" }),  redgrad : $(go.Brush, "Linear", { 0: "#C45245", 1: "#871E1B" }),  whitegrad : $(go.Brush, "Linear", { 0: "#F0F8FF", 1: "#E6E6FA" }),  bigfont : "bold 8pt Helvetica, Arial, sans-serif",  smallfont : "bold 6pt Helvetica, Arial, sans-serif",    }  return options; },  textStyle(){  return {   margin: 6,   wrap: go.TextBlock.WrapFit,   textAlign: "center",   editable: true,   font: this.getOption()['bigfont']  }  },  init(){  this.myDiagram =   $(go.Diagram, "myDiagramDiv",    {    isReadOnly: true,    // have mouse wheel events zoom in and out instead of scroll up and down    "toolManager.mouseWheelBehavior": go.ToolManager.WheelNone,    initialAutoScale: go.Diagram.Uniform,    "linkingTool.direction": go.LinkingTool.ForwardsOnly,    initialContentAlignment: go.Spot.Center,    layout: $(go.LayeredDigraphLayout, { isInitial: false, isOngoing: false, layerSpacing: 50 }),    "undoManager.isEnabled": true    });    //默认节点模板  this.myDiagram.nodeTemplate =   $(go.Node, "Auto",    new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),    // define the node's outer shape, which will surround the TextBlock    $(go.Shape, "Rectangle",    { fill: this.getOption()['yellowgrad'], stroke: "black",     portId: "", fromLinkable: true, toLinkable: true, cursor: "pointer",     toEndSegmentLength: 50, fromEndSegmentLength: 40 }),    $(go.TextBlock, "Page",    { margin: 6,     font: this.getOption()['bigfont'],     editable: true },    new go.Binding("text", "text").makeTwoWay()));   // replace the default Link template in the linkTemplateMap   this.myDiagram.linkTemplate =    $(go.Link, // the whole link panel     new go.Binding("points").makeTwoWay(),     { curve: go.Link.Bezier, toShortLength: 15 },     new go.Binding("curviness", "curviness"),     $(go.Shape, // the link shape     { stroke: "#2F4F4F", strokeWidth: 2.5 }),     $(go.Shape, // the arrowhead     { toArrow: "kite", fill: "#2F4F4F", stroke: null, scale: 2 })     );  },  /**  * options:{  * category  * shape:RoundedRectangle/Rectangle  * shapeOptions:{  * fill:bluegrad/greengrad/yellowgrad/null/redgrad/whitegrad 自定义的  * stroke: "black",  * portId:""  * fromLinkable:true  * toLinkable:  * cursor:"pointer"  * fromEndSegmentLength:40  * toEndSegmentLength  * strokeWidth  *   * }  * textStyle:{  *  margin: 9,  *  maxSize: new go.Size(200, NaN),  *  wrap: go.TextBlock.WrapFit,  *  editable: true,  *  textAlign: "center",  *  font: smallfont   * },  *   * }  */  addNodeTemplate(options){  let fill = this.getOption()[options.shapeOptions.fill];  options.shapeOptions.fill = fill;  this.myDiagram.nodeTemplateMap.add(options.category,   $(go.Node, "Auto",   new go.Binding("location", "loc", go.Point.parse).makeTwoWay(go.Point.stringify),   $(go.Shape, options.shape,options.shapeOptions),   $(go.TextBlock, this.textStyle(),    new go.Binding("text", "text").makeTwoWay())   ));  }, }}</script>

不满意的地方:

  1. 免费版gojs是有水印的,百度搜索“gojs如何去水印”有一堆答案,我就不写了。
  2. 因为要自己手动去掉水印,所以我只能手动下载go.js放在我自己的组件目录下,但是这个文件太大了,800+KB,npm run dev 的时候停在这里停了好久。有时候还爆出“......maximun ....500KB”的错误,我也不知道是什么原因,不知道有什么方法,有的话麻烦通知我。
  3. 代码写法有点太繁琐

这是我自己包装的代码地址:https://github.com/LRY1994/vue-lib/tree/master/src/components/process-go

jointjs

相比Dagre-D3和jsPlumb,JointJS的API很详细,代码量少,连接线有多种选择,封装了多种常用的形状,而且能画的图很多,官方也给了一些demo可以参考。

github : https://github.com/clientIO/joint

效果图

可以通过npm install jointjs -save安装

参照了很多demo和文档,用的是矩形,但是可以设置圆角的度数变成椭圆形,其他形状我就无力了。

可以自定义矩形的样式和矩形框里面的文字样式

//data.vue<script>export default { data(){  var userClass = {//这个要参照SVG属性   /**shapeStyle    * fill:填充的背景颜色    stroke: 边框颜色    strokeWidth: 边框宽度    rx: 圆角    ry:     */   shapeStyle:{//矩形样式    fill:{     type: 'linearGradient',     stops: [      {offset: '0%', color: '#98FB98'},      {offset: '100%', color: '#9ACD32'}     ],    },    rx:150,    ry:15   },   /**    * textStyle    * fontWeight    * fontSize    *     */   textStyle:{//文本样式    fontWeight:'bold'   }   };  return{   graphData :{    node:{     '100':{text:'用户提交资料',category:userClass},     '101':{text:'用户完善资料',category:userClass},     '102':{text:'用户确认完成',category:userClass},     '103':{text:'用户撤销',category:userClass},     '200':{text:'供应商驳回'},     '201':{text:'供应商接单'},     '202':{text:'供应商完工'},     '203':{text:'等待供应商处理'},     '300':{text:'系统交付出错'}        },    edge :{//每个点都要写     '100': ['200','201','103'],      '101': ['201'],     '102':[],     '103': ['100'],     '200': ['101'],         '201': ['202','300'],     '202': ['102'],         '203': ['102'],      '300': ['203'],        },   }  } }}</script>
<template><div id="container"> <p style="background-color:#EEEEEE;margin:0;padding:5px;font-size:0.9em"> 您当前处于 <span class="tip">用户提交资料</span> 步骤  下一步等待<span class="tip">供应商接单</span> <el-button type="text" v-if="show===false" @click="show=true">展开</el-button> <el-button type="text" v-else @click="show=false">收起</el-button>  </p> <div id="myholder" v-show="show"></div></div></template>
<script>window.joint=require('jointjs');var Shape = joint.dia.Element.define('default.Rectangle', {    attrs: {    rect: {    refWidth: '100%',    refHeight: '100%',    //下面这些可以自己设置    fill:{     type: 'linearGradient',     stops: [      {offset: '0%', color: '#B0E0E6'},//渐变开始      {offset: '100%', color: '#F0F8FF'}//渐变结束     ]    },    stroke: '#B0E0E6',    strokeWidth: 1,    rx: 5,//圆角    ry: 5   },   text: {    refX: '50%',    refY: '50%',            textVerticalAnchor: 'middle',    textAnchor: 'middle',    fontSize: 10      }   }      },  {   markup: '<rect/><text/>',   setText: function(text) {        return this.attr('text/text', text || '');  },  setShapeStyle:function(shapeStyle){   let newstyle = Object.assign({},this.attr('rect'),shapeStyle);   return this.attr('rect',newstyle)  },    setTextStyle:function(textStyle){   let newstyle = Object.assign({},this.attr('text'),textStyle);   return this.attr('text',newstyle)  } });var Link = joint.dia.Link.define('default.Link', {  attrs: {   '.connection': {    stroke: '#2F4F4F',//线    strokeWidth: 1,    pointerEvents: 'none',    targetMarker: {//箭头     type: 'path',     fill: '#2F4F4F',//填充颜色     stroke: '#2F4F4F',//边框颜色     strokeWidth:'1',     d: 'M 2 -2 0 0 2 2 z'//形状    }   }  },  connector: {   name: 'rounded'  },  z: -1,  weight: 1,  minLen: 1,  labelPosition: 'c',  labelOffset: 10,  labelSize: {   width: 50,   height: 30  },  labels: [{   markup: '<rect/><text/>',   attrs: {    text: {     fill: 'gray',     textAnchor: 'middle',     refY: 5,     refY2: '-50%',     fontSize: 10,     cursor: 'pointer'    },    // rect: {    //  fill: 'lightgray',    //  stroke: 'gray',    //  strokeWidth: 2,    //  refWidth: '100%',    //  refHeight: '100%',    //  refX: '-50%',    //  refY: '-50%',    //  rx: 5,    //  ry: 5    // }   },   size: {    width: 50, height: 10   }  }] }, {  markup: '<path class="connection"/><g class="labels"/>',    connect: function(sourceId, targetId) {   return this.set({    source: { id: sourceId },    target: { id: targetId }   });  },  setLabelText: function(text) {   return this.prop('labels/0/attrs/text/text', text || '');  } });var ElementView = joint.dia.ElementView.extend({  pointerdown: function () {   // this._click = true;   // joint.dia.ElementView.prototype.pointerdown.apply(this, arguments);  },  pointermove: function(evt, x, y) {   // this._click = false;   // joint.dia.ElementView.prototype.pointermove.apply(this, arguments);  },  pointerup: function (evt, x, y) {   // if (this._click) {   //  // triggers an event on the paper and the element itself   //  this.notify('cell:click', evt, x, y);    // } else {   //  joint.dia.ElementView.prototype.pointerup.apply(this, arguments);   // }  } });var LinkView = joint.dia.LinkView.extend({ addVertex: function(evt, x, y) {}, removeVertex: function(endType) {}, pointerdown:function(evt, x, y) {}});export default {  data(){  return{   graph:null,   paper:null,   show:true  }   }, props:{  graphData:{   type:Object,   required:true  } }, mounted(){  let w = document.getElementById('container').width ;   this.graph = new joint.dia.Graph;  this.paper = new joint.dia.Paper({   el: document.getElementById('myholder'),   width: w,   height: 250,      model: this.graph,   elementView: ElementView,//禁止拖拽   linkView:LinkView//禁止拖拽  });  this.layout(); }, methods:{  getWidthandHeight(label){   let maxLineLength = _.max(label.split('/n'), function(l) { return l.length; }).length,   // Compute width/height of the rectangle based on the number   // of lines in the label and the letter size. 0.6 * letterSize is   // an approximation of the monospace font letter width.    letterSize = 8,    width = 2 * (letterSize * (0.6 * maxLineLength + 1)),    height = 2 * ((label.split('/n').length + 1) * letterSize);   return {width,height}  },  getLayoutOptions() {   return {    // setVertices: false,    // setLabels: false,    // ranker:'longer-path',//'tight-tree'/'network-simplex',    rankDir: 'LR',    align: 'UR',    rankSep:0,    edgeSep:0,    nodeSep:0,   };  },  buildGraphFromAdjacencyList(adjacencyList) {   let elements = [],links = [],obj,size,node;   const _this=this;   const map=this.graphData.node;   Object.keys(adjacencyList).forEach(function(parentId) {    // Add element    obj =map[parentId];    size = _this.getWidthandHeight(obj.text);    node =new Shape({id:parentId,size:size}).setText(obj.text);    if(obj.category&&obj.category.shapeStyle){     node = node.setShapeStyle(obj.category.shapeStyle);    }    if(obj.category&&obj.category.textStyle){     node = node.setTextStyle(obj.category.textStyle);    }    elements.push(node);        // Add links    adjacencyList[parentId].forEach(function(childId) {     links.push(      new Link().connect(parentId, childId)// .setLabelText(parentLabel + '-' + childLabel)                );    });   });   return elements.concat(links);  },  layout() {      let cells = this.buildGraphFromAdjacencyList(this.graphData.edge);    this.graph.resetCells(cells);   joint.layout.DirectedGraph.layout(this.graph, this.getLayoutOptions());  }, }}</script><style>#myholder { border: 1px solid lightgray; margin-bottom:20px; padding-left:20px}.tip{ color:#9ACD32; font-size:0.9em; font-weight:bold; padding:5px;}</style>

这是我自己包装的代码地址:https://github.com/LRY1994/vue-lib/tree/master/src/components/process-joint

这个目前看来还算满意

jsplumb

这个看了官网,不太友好,而且下载只有一个js文件,没有demo代码,不知如何下手

参考资料:

https://gojs.net/latest/samples/pageFlow.html
http://www.daviddurman.com/assets/autolayout.js
http://resources.jointjs.com/demos/layout

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

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表