This year due to the project needs to upgrade the customer's process management system, which includes process visualization.So after investigating the tools like D3,js, GooFlow.js, G6-Editor and so on, we found that D3,js learning cost is too high, G6-Editor function is basically enough, but it is hard to zoom in and out graphics and move connectors, and GooFlow.js and G6-Editor are currently closed source, so we decided to try to write a process editor.
Since Visio was used as the basic way to draw flowcharts before, the editor's operating style is basically the same as that of Visio and absorbs some of the G6-Editor's.
The HTML content is as follows:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title>Test Page</title> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <link rel="shortcut icon" href="assets/img/favicon.jpg"> <link rel="stylesheet" href="assets/css/bootstrap.min.css" type="text/css" /> <link rel="stylesheet" href="assets/css/font-awesome.min.css" type="text/css" /> <link rel="stylesheet" href="assets/css/editor.css" type="text/css" /> </head> <body> <div style="width:99%"> <div id="toolbar" class="toolbar"> <i data-command="undo" class="fa fa-mail-reply" title="Revoke"></i> <i data-command="redo" class="fa fa-mail-forward" title="redo"></i> <i data-command="delete" class="fa fa-trash-o" title="delete"></i> <i data-command="save" class="fa fa-save" title="Preservation"></i> </div> <div class="row" style="width:99%"> <div class="col-md-2"> <div id="itempannel" class="itempannel"> <div class="node" data-type="node" data-shape="capsule" data-size="80*40" data-label="start" data-color="rgba(200,255,200,1)" data-edgecolor="rgb(10,255,10,1)" > <img draggable="false" src="assets/img/start.svg" alt="" scrset=""> </div> <div class="node" data-type="node" data-shape="rect" data-size="100*50" data-label="General Node" data-color="#E6F7FF" data-edgecolor="#1890FF" > <img draggable="false" src="assets/img/normal.svg" alt="" scrset=""> </div> <div class="node" data-type="node" data-shape="rhomb" data-size="100*80" data-label="judge" data-color="#E6FFFB" data-edgecolor="#5CDBD3" > <img draggable="false" src="assets/img/judge.svg" alt="" scrset=""> </div> <div class="node" data-type="node" data-shape="capsule" data-size="80*40" data-label="End" data-color="rgba(255,200,200,1)" data-edgecolor="rgb(255,50,50,1)" > <img draggable="false" src="assets/img/end.svg" alt="" scrset=""> </div> </div> </div> <div class="col-md-7"> <div id="canvas"></div> </div> <div class="col-md-3"> <div id="detailpannel" class="detailpannel"> <div><b>Attribute details</b></div> <div id="nodedetail" style="display:none"> <div class="row"> <label class="col-sm-4 control-label"> Node name </label> <div class="col-sm-8"> <input id="nodename" type="text" class="form-control" /> </div> </div> <div class="row"> <label class="col-sm-4 control-label"> font size </label> <div class="col-sm-8"> <input id="fontsize_node" type="text" class="form-control" /> </div> </div> <div class="row"> <label class="col-sm-4 control-label"> Custom Properties </label> <div class="col-sm-8"> <input id="nodecustom" type="text" class="form-control" /> </div> </div> </div> <div id="linedetail" style="display:none"> <div class="row"> <label class="col-sm-4 control-label"> Line name </label> <div class="col-sm-8"> <input id="linename" type="text" class="form-control" /> </div> </div> <div class="row"> <label class="col-sm-4 control-label"> font size </label> <div class="col-sm-8"> <input id="fontsize_line" type="text" class="form-control" /> </div> </div> <div class="row"> <label class="col-sm-4 control-label"> Custom Properties </label> <div class="col-sm-8"> <input id="linecustom" type="text" class="form-control" /> </div> </div> </div> </div> </div> </div> </div> <script type="text/javascript" src="assets\js\popper.min.js"></script> <script type="text/javascript" src="assets\js\jquery.min.js"></script> <script type="text/javascript" src="assets\js\bootstrap.min.js"></script> <script type="text/javascript" src="assets\js\graphEditor.js"></script> <script type="text/javascript" src="assets\js\index.js"></script> </body> </html>
Where graphEditor.js is the editor's JS file and the editor's canvas is loaded in a container with id canvas.
The index.js file contains the following:
const data = {}; //Node Format data.nodes = [ { color:"rgba(200,200,255,1)", customProperties: { nodestyle: "11" }, edgeColor:"#1890FF", id: "9471a484-7a2e-4ca9-949d-6ec4b495a1a2", index: 1, label: "Test Load Node", shape: "rect", size: "100*50", type: "node", x: 282, y: 222 }, { color:"rgba(200,200,255,1)", customProperties: { nodestyle: "22" }, edgeColor:"#1890FF", id: "9471a484-7a2e-4ca9-949d-6ec4b495a1a3", index: 2, label: "Test Load Judgment", shape: "rhomb", size: "100*80", type: "node", x: 282, y: 422, fontSize: "12px" } ] //Line Format data.lines = [ { color:"rgba(0,0,0,1)", customProperties: { btnstyle: "test" }, index: 3, label: "Test Line 1", fontSize: "12px", fromConOrder: 3, source: "9471a484-7a2e-4ca9-949d-6ec4b495a1a2", type: "line", endPoint: { x: 81, y: 210 }, inflexionPoint: [ { x: 282, y: 272 }, { x: 81, y: 272 } ] }, { color:"rgba(0,0,0,1)", customProperties: { btnstyle: "test" }, index: 4, label: "Test Line 2", fontSize: "14px", toConOrder: 1, startPoint: { x: 555, y: 447 }, target: "9471a484-7a2e-4ca9-949d-6ec4b495a1a3", type: "line", inflexionPoint: [ { x: 555, y: 357 }, { x: 282, y: 357 } ] } ] //Create Editor const editor = new GraphEditor(); //Editor Load Data //editor.load(data); //Binding Element Container editor.itemPannel = 'itempannel'; //Binding Detail Properties Bar editor.detailPannel = 'detailpannel'; //Binding Toolbar editor.toolbar = 'toolbar'; const nodeDetail = $('#nodedetail'); const lineDetail = $('#linedetail'); const nodeName = $('#nodename'); const lineName = $('#linename'); const nodeCustom = $('#nodecustom'); const lineCustom = $('#linecustom'); const nodeFontSize = $('#fontsize_node'); const lineFontSize = $('#fontsize_line'); //Select Element Events editor.on('selectedElement', function(e) { if(e.element.isNode){ lineDetail.hide(); nodeDetail.show(); nodeName.val(e.element.label); nodeFontSize.val(e.element.fontSize); nodeCustom.val(e.element.customProperties.nodestyle); } else if (e.element.isLine){ nodeDetail.hide(); lineDetail.show(); lineName.val(e.element.label); lineFontSize.val(e.element.fontSize); lineCustom.val(e.element.customProperties.btnstyle); } }); //Click Canvas Event editor.on('click', function(e) { if(!e.element){ nodeDetail.hide(); lineDetail.hide(); } }); //Cancel Event editor.on('undo', function(e) { nodeDetail.hide(); lineDetail.hide(); //console.log(e.data); }); //Redo Events editor.on('redo', function(e) { nodeDetail.hide(); lineDetail.hide(); //console.log(e.data); }); //Save Events editor.on('save', function(e) {console.log(e.data)}); nodeName.change(function(e){ updateEditor(e, 'label'); }); lineName.change(function(e){ updateEditor(e, 'label'); }); nodeFontSize.change(function(e){ updateEditor(e, 'fontSize'); }); lineFontSize.change(function(e){ updateEditor(e, 'fontSize'); }); nodeCustom.change(function(e){ updateEditor(e, 'nodestyle'); }); lineCustom.change(function(e){ updateEditor(e, 'btnstyle'); }); function updateEditor(e, name){ const property = {}; property.name = name; property.value = $('#' +e.target.id).val(); if (editor.selectedElement){ editor.update(editor.selectedElement.id, property); }; }
GraphEditor method list:
- load(data): Used to load data, the structure of the data refers to index.js.
The properties of a node are as follows:
- update(id,property)
id: the number of the element
Property:{name: name of the property to be updated, value: updated value}
GraphEditor Event List:
- selectedElement: Any canvas element is selected to trigger, and the element property of the event object holds the selected element
-
Click: click on the canvas container to trigger
-
undo: undo action trigger
-
Redo: redo action trigger
- Save: the save action triggers, the event object's data attribute stores all elements in the canvas, and the editor object's data attribute also contains all elements of the canvas
GraphEditor shortcut list:
- Delete: Delete elements from the canvas
- Ctrl+z: Undo
- Ctrl+y: Redo
- Ctrl+s: Save
Demo download address: https://files.cnblogs.com/files/lixincloud/GraphEditorDemo.rar