1.fabric.js
在決定使用mxgraph.js開發流程圖之前,嘗試過用fabric.js來開發,結果發現並沒有想象中的那么簡單,而且用戶體驗非常差,下面是體驗地址:
workFlow
直到遇到一個致命bug,當我准備加一個雙擊圖形輸入文字功能,花了
一點時間搗鼓了一下,通過group組合實現了此功能,但是,第一次雙擊輸入正常,第二次再次雙擊就出現莫名其妙的情況,最后反饋給作者說下個版本
不准備解決,看了下issues,也發現了類似的問題,此方案就此放棄。
2.GoJs
第二次有人推薦我使用GoJs,看了下功能確實強大,也找到了符合我想要的流程圖應用,但是。。。。嘗試運行簡單的例子同步到Vue,沒出什么問題,當同步
一個簡單的流程圖示例,各種問題,搗鼓了很久還是沒能運行成功,最重要的它的api寫法簡直太難受,此方案也就此放棄。官方示例:
GoJs
3.mxgraph.js
先上圖來一波

體驗地址:
mxFlow
說一下基礎api的使用以及一些坑
1.定義全局Cell樣式
this.style = new Object(); this.style[mxConstants.STYLE_DASHED] = 0;//0實線 1虛線
this.style[mxConstants.STYLE_STROKEWIDTH] = 1;//邊框寬度
// this.style[mxConstants.STYLE_GRADIENTCOLOR] = 'red';//漸變色
this.style[mxConstants.STYLE_GRADIENT_DIRECTION] = mxConstants.DIRECTION_WEST;//漸變方向 east-東 west-西 north-北 south-南
this.style[mxConstants.STYLE_FONTFAMILY] = "consolas";//字體
this.style[mxConstants.STYLE_FONTSTYLE] = 0;//1-加粗 2-斜體 4-下划線
this.style[mxConstants.STYLE_HORIZONTAL] = 1;//1-水平 0-垂直
this.style[mxConstants.STYLE_LABEL_POSITION] = "center";//文字居中 結合下面屬性控制
this.style[mxConstants.STYLE_VERTICAL_LABEL_POSITION] = "middle";// this.graph.getStylesheet().putDefaultVertexStyle(this.style);//put到全局style中
2.定義全局Edge、label樣式
this.style = this.graph.getStylesheet().getDefaultEdgeStyle(); this.style['fontSize'] = this.fontSize; this.style['verticalAlign'] = 'bottom'; this.style[mxConstants.STYLE_ROUNDED] = true; this.style[mxConstants.STYLE_EDGE] = mxEdgeStyle.ElbowConnector; this.style[mxConstants.STYLE_LABEL_BACKGROUNDCOLOR] = "white";//transparent 連線文字背景顏色
this.style[mxConstants.STYLE_ORTHOGONAL_LOOP] = 1; this.style[mxConstants.STYLE_JETTY_SIZE] = "auto";
3.局部樣式
let style = new Object(); style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_IMAGE; style[mxConstants.STYLE_PERIMETER] = mxPerimeter.RectanglePerimeter; style[mxConstants.STYLE_IMAGE] = '../../../static/img/star_200.png'; style[mxConstants.STYLE_FONTCOLOR] = 'black'; this.graph.getStylesheet().putCellStyle('image', style);//自定義背景style
this.graph.insertVertex(this.parent, null, 'star', x, y, 100, 100, 'image');//使用方式
4.修改全局Cell默認樣式 Edge同理
let style = this.graph.getStylesheet().getDefaultVertexStyle(); style[mxConstants.STYLE_FONTCOLOR] = this.color;
5.設置單個或者多個Cell樣式 Edge同理
this.graph.setCellStyles(mxConstants.STYLE_GRADIENT_DIRECTION, this.curDirGradient);//第一種方式
this.graph.setCellStyles(mxConstants.STYLE_FILLCOLOR, "none", [vertex]);//第二種方式
6.復制
let selectionCells = this.graph.getSelectionCells(); mxClipboard.copy(this.graph, selectionCells);
7.粘貼
mxClipboard.paste(this.graph);
8.剪切
let selectionCells = this.graph.getSelectionCells(); mxClipboard.cut(this.graph, selectionCells);
9.放大
this.graph.zoomIn();
10.縮小
this.graph.zoomOut();
11.撤銷與還原
初始化: this.undoMng = new mxUndoManager(); let listener = (sender, evt) => { this.undoMng.undoableEditHappened(evt.getProperty('edit')); }; this.graph.getModel().addListener(mxEvent.UNDO, listener); his.graph.getView().addListener(mxEvent.UNDO, listener); 撤銷: this.undoMng.undo(); 還原: this.undoMng.redo();
12.組合
let vertex = new mxCell(null, new mxGeometry(0, 0)); vertex.setVertex(true); this.graph.groupCells(vertex, 0, this.graph.getSelectionCells());
13.分解
this.graph.ungroupCells(this.graph.getSelectionCells());
14.加載xml自定義圖形
try { let req = mxUtils.load(this.staticPath+'xml/basic.xml');//此處路徑寫成項目資源文件目錄
let root = req.getDocumentElement(); let shape = root.firstChild; while (shape != null) { if (shape.nodeType == mxConstants.NODETYPE_ELEMENT) { let name = shape.getAttribute('name'); this.basicItems.push(name);//存儲讀取的shape名稱數組
mxStencilRegistry.addStencil(name, new mxStencil(shape)); } shape = shape.nextSibling; } } catch (e) { mxUtils.alert('Cannot load' + e); }
使用方式: let basic = document.getElementById("basic"); this.basicItems.forEach((name, index) => { basic.append(this.createItem("", 45, 45, "shape=" + name)); });
createItem方法: createItem(title, width, height, style) { let vertex = new mxCell(null, new mxGeometry(0, 0, width, height), style); vertex.setVertex(true); let elt = document.createElement('div'); elt.className = 'el-col el-col-8 basic'; // elt.style.overflow = 'hidden';
// Blocks default click action
// mxEvent.addListener(elt, 'click', function(evt)
// {
// mxEvent.consume(evt);
// });
// this.graph.view.scaleAndTranslate(1, 0, 0);
this.graph.setCellStyles(mxConstants.STYLE_FILLCOLOR, "none", [vertex]); this.graph.setCellStyles(mxConstants.STYLE_STROKEWIDTH, 3, [vertex]); this.graph.setCellStyles(mxConstants.STYLE_STROKECOLOR, "#515151", [vertex]); this.graph.setCellStyles(mxConstants.STYLE_SHADOW, false, [vertex]); this.graph.setCellStyles(mxConstants.STYLE_ALIGN, mxConstants.ALIGN_CENTER, [vertex]); this.graph.setCellStyles(mxConstants.STYLE_IMAGE_WIDTH, 48, [vertex]); this.graph.setCellStyles(mxConstants.STYLE_IMAGE_HEIGHT, 48, [vertex]); this.graph.addCell(vertex); let node; node = this.graph.view.getCanvas().ownerSVGElement.cloneNode(true); this.graph.getModel().clear(); elt.appendChild(node); return elt; },//創建自定義html包裹的svg
15.一些坑
有些全局樣式也可以直接修改,(不用像上面那樣put)例如: mxConstants.VERTEX_SELECTION_COLOR = "#29B6F2"; 鼠標框選 不顯示背景顏色 new mxRubberband(this.graph); 解決辦法添加以下css div.mxRubberband { position: absolute; overflow: hidden; border-style: solid; border-width: 1px; border-color: #0000FF; background: #3481D7; } 加載xml自定義圖形上面14點已完整說明。
暫時就介紹那么多,還有很多細節設置就下次再說了。
歡迎進群交流(927465926)