mxGraph介绍

一、简介

1、mxGraph是什么?

先放上官方的文档:

API:http://jgraph.github.io/mxgraph/docs/js-api/files/index-txt.html

Demo:http://jgraph.github.io/mxgraph/javascript/index.html

简单来说,mxGraph是一个JavaScript工具库,实现图形的可视化交互。mxGraph主要包含一个JavaScript文件,mxGraph的全部函数都在这个文件中。它需要被加载到一个浏览器的Web页面的Javascript中并执行在HTML容器中。它结构简单,只要一个web服务器来提供html页面和一个支持JavaScript的浏览器就可以了。

2、mxGraph有什么优点?

  • 不需要第三方插件,纯js的工具库,兼容性非常好。
  • 涉及到的技术都是开源的。
  • 支持多种语言(Java、JavaScript、PHP、.NET),所绘制的图形可以在主流浏览器以及原生应用上使用。
  • mxGraph默认绘制的是svg图形,所以支持后端语言进行预渲染,同时也支持保存和导出,转化为位图也非常方便。

3、mxGraph有什么缺点?

  • API是全英文的。
  • 组件默认的样式比较丑,需要自己优化样式。

4、mxGraph的使用场景有哪些?

官方给出的场景有四个:图形可视化、图形交互、图形布局、图形分析。比如:过程图、工作流和BPM的可视化图表、流程图、交通或水流量、 数据库可视化、网络和电信显示、映射应用和地理信息系统、UML图、电子线路、金融、 超大规模集成电路和社会网络、数据挖掘、生化、生态循环、实体和因果关系和组织图表。

  • 图形可视化

  图形可视化是mxGraph的主打功能,这个很好理解,就是把一些抽象的概念用图形来表示,比如常见的流程图、思维导图、实体关系图等。 需要注意的是mxGraph所绘制的图主要是由“点”(也包括矩形、圆形这类基本形状)和“边”组成的,下图是官方提供的一张样图。 

  

  • 图形交互

  mxGraph除了绘制图形之外还提供了丰富的编辑功能,比如拖拽、选择、复制、调整大小等。 mxGraph甚至还专门提供了一个API类用来支持在线编辑器。

  

  • 图形布局

  非常重要的一个功能,能自动排列图形元素。 mxGraph提供了多种布局方式,比如树形布局、栈式布局、圆形布局。

  

  • 图形分析

  支持图相关的算法分析,比如找出图中两个节点的最短路径。

  

 

 

二、mxGraph使用

1、获取mxGraph包

mxGraph可以从github项目上下载:https://github.com/jgraph/mxgraph

2、导入项目中

从下载的文件中可以获得一系列的js文件,将js文件复制到项目中,在html中引用mxClient.js(mxClient.js会引用其他的工具类)

 

 

 

3、参考mxGraph的API进行开发()

  • 新建第一个图形(点+线)
  • 给画布增加一些辅助属性
  • 自定义节点的样式
  • 自定义布局
  • 增加操作按钮
  • 查看图形的xml
  • 通过解析xml展示图形
  • 添加右键事件
  • 定义拖拽事件

附上源代码:

index.html

 1 <!DOCTYPE html>
 2 <html lang="en">
 3 <head>
 4     <meta charset="UTF-8">
 5     <title>mxGraph</title>
 6     <link href="css/index.css" rel="stylesheet">
 7 </head>
 8 <body onload="main(document.getElementById('graphContainer'))">
 9     <!-- 操作按钮容器 -->
10     <div id="methods">
11         <div id="buttons" style="height: 50px;"></div>
12     </div>
13     <!-- 拖拽组件 -->
14     <div id="drag">
15         <span id="in1">表输入</span>
16         <span id="out1">表输出</span>
17         <span id="trans1">字符串替换</span>
18         <span id="scp1">执行存储过程</span>
19     </div>
20     <!-- 画布区域 -->
21     <div id="graphContainer"></div>
22 </body>
23 <script src="js/mxClient.js"></script>
24 <script src="js/index.js"></script>
25 </html>
View Code

index.js

  1 var mxBasePath = '../mxgraph';
  2 function main(container) {
  3     // 禁用鼠标右键
  4     mxEvent.disableContextMenu(container);
  5 
  6     var graph = new mxGraph(container);
  7     // 设置这个属性后节点之间才可以连接
  8     graph.setConnectable(true);
  9     //开启节点不可改变大小
 10     graph.setCellsResizable(false);
 11     //边被拖时,始终保持连接
 12     graph.setDisconnectOnMove(false);
 13     //开启tooptip提示
 14     graph.setTooltips(true);
 15     // 启用对齐线帮助定位
 16     mxGraphHandler.prototype.guidesEnabled = true;
 17     // 设置启用,就是允不允许你改变CELL的形状内容
 18     graph.setEnabled(true);
 19 
 20     //定义节点样式
 21     //API:https://jgraph.github.io/mxgraph/docs/js-api/files/util/mxConstants-js.html
 22     var nodeStyle = {};
 23     nodeStyle[mxConstants.STYLE_FILLCOLOR] = "#3CAEA3";
 24     nodeStyle[mxConstants.STYLE_FONTSIZE] = 15;
 25     nodeStyle[mxConstants.STYLE_STROKE_COLOR] = "white";
 26     nodeStyle[mxConstants.STYLE_FONTCOLOR] = "white";
 27     nodeStyle[mxConstants.STYLE_ROUNDED] = 1;
 28     // 把定义好的样式object push到stylesheet
 29     graph.getStylesheet().putCellStyle("nodeStyle", nodeStyle);
 30 
 31     // 开启区域选择
 32     new mxRubberband(graph);
 33     const parent = graph.getDefaultParent();
 34     graph.getModel().beginUpdate();
 35     //定义布局(可以使用多种布局)
 36     var layout = new mxEdgeLabelLayout(graph);
 37     try {
 38         /*insertVertex参数
 39         **参数1:parents 生成节点要插入的父级容器
 40         **参数2:null 此处可以设置节点的id,便于识别节点,null为默认id
 41         **参数3:label 此处设置节点的内容
 42         **参数4:设置节点大小及节点在父级容器中的相对位置*/
 43         const v1 = graph.insertVertex(parent, null, '起点,', 20, 20, 80, 30);
 44         const v2 = graph.insertVertex(parent, null, '终点', 200, 150, 80, 30, 'nodeStyle');
 45         /*insertVertex参数
 46         **参数1:parents 生成边要插入的父级容器
 47         **参数2::null 此处可以设置节点的id,便于识别边,null为默认id
 48         **参数3:label 此处设置节点的内容
 49         **参数4:边的起始节点和终止节点*/
 50         const e1 = graph.insertEdge(parent, null, 'OK', v1, v2);
 51         /*
 52         var xml=
 53             '<mxGraphModel>'+
 54             '  <root>'+
 55             '    <mxCell id="0" />'+
 56             '    <mxCell id="1" parent="0" />'+
 57             '    <mxCell id="2" value="起点," vertex="1" parent="1">'+
 58             '      <mxGeometry width="80" height="30" as="geometry" />'+
 59             '    </mxCell>'+
 60             '    <mxCell id="3" value="终点" style="nodeStyle" vertex="1" parent="1">'+
 61             '      <mxGeometry y="130" width="80" height="30" as="geometry" />'+
 62             '    </mxCell>'+
 63             '    <mxCell id="4" value="OK" style="noEdgeStyle=1;orthogonal=1;" edge="1" parent="1" source="2" target="3">'+
 64             '      <mxGeometry relative="1" as="geometry">'+
 65             '        <Array as="points">'+
 66             '          <mxPoint x="40" y="42" />'+
 67             '          <mxPoint x="40" y="118" />'+
 68             '        </Array>'+
 69             '      </mxGeometry>'+
 70             '    </mxCell>'+
 71             '  </root>'+
 72             '</mxGraphModel>';
 73         var doc = mxUtils.parseXml(xml);
 74         var codec = new mxCodec(doc);
 75         codec.decode(doc.documentElement, graph.getModel());*/
 76         layout.execute(parent);
 77     } finally {
 78         graph.getModel().endUpdate();
 79     }
 80 
 81     /****************************定义操作按钮******************************/
 82     //选中所有
 83     document.getElementById("buttons").appendChild(
 84         mxUtils.button('选中所有', function() {
 85             graph.selectAll()
 86         })
 87     )
 88 
 89     //选择一个
 90     document.getElementById("buttons").appendChild(
 91         mxUtils.button('选择一个', function() {
 92             graph.selectCell()
 93         })
 94     )
 95 
 96     //取消选择
 97     document.getElementById("buttons").appendChild(
 98         mxUtils.button('取消选择', function() {
 99             var cells = graph.getSelectionCells()
100             graph.removeSelectionCells(cells)
101         })
102     )
103 
104     //删除所选
105     document.getElementById("buttons").appendChild(
106         mxUtils.button('删除所选', function() {
107             var cells = graph.getSelectionCells()
108             graph.removeCells(cells)
109         })
110     )
111 
112     //放大节点
113     document.getElementById("buttons").appendChild(
114         mxUtils.button('放大节点', function() {
115             graph.zoomIn()
116         })
117     )
118 
119     //缩小节点
120     document.getElementById("buttons").appendChild(
121         mxUtils.button('缩小节点', function() {
122             graph.zoomOut()
123         })
124     )
125 
126     //还原节点
127     document.getElementById("buttons").appendChild(
128         mxUtils.button('还原节点', function() {
129             graph.zoomActual()
130         })
131     )
132 
133     //清空画板
134     document.getElementById("buttons").appendChild(
135         mxUtils.button('清空画板', function() {
136             graph.removeCells(graph.getChildVertices(graph.getDefaultParent()))
137         })
138     )
139 
140     //查看图形的xml
141     document.getElementById("buttons").appendChild(mxUtils.button('查看XML', function()
142     {
143         var encoder = new mxCodec();
144         var node = encoder.encode(graph.getModel());
145         mxUtils.popup(mxUtils.getPrettyXml(node), true);   //以窗口的方式展示处理
146     }));
147 
148     //添加右键事件
149     graph.popupMenuHandler.factoryMethod = function(menu, cell, evt) {
150         return createPopupMenu(graph, menu, cell, evt);
151     };
152 
153     createDragSource(graph);
154 }
155 
156 //添加右键事件
157 function createPopupMenu(graph, menu, cell, evt){
158     menu.addItem("删除步骤", "", function() {
159         var cells = graph.getSelectionCells();
160         graph.removeCells(cells);
161     });
162 }
163 
164 //定义拖拽事件
165 function createDragSource(graph) {
166     var in1 = this.createDragImage(
167         graph,
168         "in1",
169         "./images/in.png",
170         "表输入"
171     );
172     //创建输出拖动源
173     var out1 = this.createDragImage(
174         graph,
175         "out1",
176         "./images/out.png",
177         "表输出"
178     );
179     //创建转换拖动源
180     var trans1 = this.createDragImage(
181         graph,
182         "trans1",
183         "./images/replace.png",
184         "字符串替换"
185     );
186     //创建脚本拖动源
187     var scp1 = this.createDragImage(
188         graph,
189         "scp1",
190         "./images/sql.png",
191         "执行存储过程"
192     );
193 }
194 
195 //创建拖拽源
196 function createDragImage(graph, id, image, text) {
197     var img = mxUtils.createImage(image);
198     img.style.width = "30px";
199     img.style.height = "30px";
200     img.style.margin = "0px";
201     document.getElementById(id).appendChild(img);
202 
203     var style = this.getStyle(graph, image, id);
204 
205     // 检查图形中是否包含对应的elt节点
206     function containsElt(graph, elt) {
207         while (elt != null) {
208             if (elt == graph.container) {
209                 return true;
210             }
211             elt = elt.parentNode;
212         }
213         return false;
214     }
215 
216     // 在给定的位置插入一个元素
217     var funct1 = function(graph, evt, target, x, y) {
218         var cell = new mxCell(text, new mxGeometry(0, 0, 50, 50), id);
219         cell.vertex = true;
220         var cells = graph.importCells([cell], x, y, target); //插入元素、位置、大小
221     };
222 
223     // 禁用IE浏览器中的DnD功能(这是为了跨浏览器平台而设计的,见下文)
224     if (mxClient.IS_IE) {
225         mxEvent.addListener(img, "dragstart", function(evt) {
226             evt.returnValue = false;
227         });
228     }
229 
230     // 创建拖动源的预览
231     var dragElt = document.createElement("div");
232     dragElt.style.border = "dashed black 1px";
233     dragElt.style.width = "120px";
234     dragElt.style.height = "40px";
235 
236     // 在点击拖动源图标时提供预览。 预览是提供的仅仅是拖动源的图片
237     // 只有拖动源到容器内时才会显示元素的坐标预览
238 
239     var ds = mxUtils.makeDraggable(
240         img,
241         graph,
242         funct1,
243         dragElt,
244         null,
245         null,
246         graph.autoscroll,
247         true
248     );
249 
250     //从拖动源拖动时显示导航线。
251     //注意,对图形中已存在的元素拖动时显示导航线不在本方法约束范围。
252     ds.isGuidesEnabled = function() {
253         return graph.graphHandler.guidesEnabled;
254     };
255 
256     //从拖动源拖动元素到图形以外的区域时,显示拖动源图片预览
257     ds.createDragElement = mxDragSource.prototype.createDragElement;
258 }
259 
260 function getStyle(graph, url, styleName) {
261     // 声明一个object
262     var style = {};
263     // 克隆一个object
264     style = mxUtils.clone(style);
265     style[mxConstants.STYLE_SHAPE] = mxConstants.SHAPE_LABEL; // 不设置这个属性 背景图片不出来
266     // 边框颜色
267     style[mxConstants.STYLE_STROKECOLOR] = "#15428b";
268     //圆角
269     style[mxConstants.STYLE_ROUNDED] = "1";
270     // 边框大小
271     style[mxConstants.STYLE_STROKEWIDTH] = "0.5px";
272     // 字体颜色
273     style[mxConstants.STYLE_FONTCOLOR] = "#000";
274     // 文字水平方式
275     style[mxConstants.STYLE_ALIGN] = mxConstants.ALIGN_right;
276     // 文字垂直对齐
277     style[mxConstants.STYLE_VERTICAL_ALIGN] = mxConstants.ALIGN_TOP;
278     // 字体大小
279     style[mxConstants.STYLE_FONTSIZE] = 14;
280     style[mxConstants.STYLE_FILLCOLOR] = "transparent";
281     // 底图水平对齐
282     style[mxConstants.STYLE_IMAGE_ALIGN] = mxConstants.ALIGN_LEFT;
283     // 底图垂直对齐
284     style[mxConstants.STYLE_IMAGE_VERTICAL_ALIGN] = mxConstants.ALIGN_TOP;
285     // 图片路径
286     //style[mxConstants.STYLE_IMAGE] = 'images/icons48/gear.png';
287     style[mxConstants.STYLE_IMAGE] = url; //'./images/i_assignedSlave.png';
288     // 背景图片宽
289     style[mxConstants.STYLE_IMAGE_WIDTH] = 40;
290     // 背景图片高
291     style[mxConstants.STYLE_IMAGE_HEIGHT] = 40;
292 
293     // 上间距设置
294     // 即使下边定义了全局设置,但这里单独设置上边间距仍单独有效
295     // style[mxConstants.STYLE_SPACING_TOP] = 'spacingTop';
296     // 四边间距设置
297     style[mxConstants.STYLE_SPACING] = 1;
298     style[mxConstants.STYLE_VERTICAL_LABEL_POSITION] =
299         mxConstants.ALIGN_BOTTOM;
300     graph.getStylesheet().putCellStyle(styleName, style);
301 }
View Code

项目结构如下,红色框中的是官方下载的文件

 

posted @ 2021-11-22 22:20  Nullable=Y  阅读(1158)  评论(1)    收藏  举报