vue中使用gojs/jointjs的示例代码
因为公司项目需求,要画出相关业务的流程图,以便客户了解自己身处何处
搜索框输入 “前端流程图插件”,查了很多资料,总结一下有以下几种
flow-chart
代码写法繁琐,不是json就可以解决,效果也比较丑,pass
darge-d3
github :
效果图
下载里面的demo,改一下json就可以了
// states var states = [ "new", "submitted","finished" ,"failed","deliver", "canceled", "abolished" , "deleted","refunding","refunded"]; var map = ['新创建','已提交','已完成','提交失败',"交付中", '已取消','废除','已删除','退款中',"已退款"] // automatically label each of the nodes states.foreach(function(state,index) { g.setnode(state, { label: `${map[index]}(${state})`})}); // set up the edges g.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>
不满意的地方:
- 免费版gojs是有水印的,百度搜索“gojs如何去水印”有一堆答案,我就不写了。
- 因为要自己手动去掉水印,所以我只能手动下载go.js放在我自己的组件目录下,但是这个文件太大了,800+kb,npm run dev 的时候停在这里停了好久。有时候还爆出“......maximun ....500kb”的错误,我也不知道是什么原因,不知道有什么方法,有的话麻烦通知我。
- 代码写法有点太繁琐
这是我自己包装的代码地址: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
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。