## mxgraph介绍github地址:https://github.com/jgraph/mxgraph,源码地址:https://github.com/jgraph/mxgraph2  仿真零碎地址 http://simulator.wankeauto.com/  成果能够参考 [https://app.diagrams.net/],实现相似 visio 画图的成果,流程图是它次要的一个用处  mxgraph 是一个绘图框架,除了javascript版本,还有java版本,c#版本等  咱们应用的是javascript版本用于web端,mxgraph 只实现了画图最外围的性能, 官网内置了很多简略的demo,也有grapheditor等简单的带快捷键、工具栏,菜单性能的demomxgraph 能兼容 ie8 等比拟老的浏览器,因而代码中也有很多解决兼容性的代码,在支流浏览器中应用 svg 实现绘图,但代码中应用了 canvas 作为变量,可能容易误以为是 canvas 来实现的。  依据业务需要,咱们须要进行大量的自定义扩大(oop形式),所以须要进行大量的源码浏览,了解其实现形式,并扩大实现本人的性能。网上对于mxgraph的介绍可参考: [mxGraph 入门实例教程]: https://segmentfault.com/a/1190000018510996官网文档: https://jgraph.github.io/mxgraph/docs/manual.html  官网api阐明:https://jgraph.github.io/mxgraph/docs/js-api/files/index-txt.html  ## mxgraph源码目录构造### 1. view  > 负责图形的渲染,外部逻辑管制,对外提供api    - 外围类 mxGraph,应用了调停者模式,通过扩大这个类,能够自定义很多性能, 咱们内部应用的很多 api 都在这个文件内  - mxGraphView: 元件从新渲染逻辑,计算元件地位、背景网格等    - mxCell:保留元件的地位信息(geometry)    - mxCellState: 依据mxCell数据,保留元件实在地位,mxGraphView每次从新渲染会从新生成    - mxCellRenderer: 依据mxCellState信息渲染出svg图形、label、control    - mxEdgeStyle: 连接线的形态,反对直线、折线等其余形态,目前应用的是 elbowEdgeStyle    - mxPerimeter: 不同形态的边缘地位计算方法  ### 2. util  次要工具类实现:日志打印、底层画图api、工具栏、撤销、申请、拖拽  mxPoint、mxRectangle等根本数据类型  mxEventSource,mxEventObject 实现公布订阅模式### 3. model  外围模块mxGraphModel,所有对mxCell的操作都都由这个模块负责,扭转mxCell的geometry、父元素、value、style等,撤销性能次要由mxUndoManager、mxUndoableEdit、和这个目录下的文件实现### 4. handle  文件夹内蕴含了解决鼠标事件的类,比方鼠标选中、图形放大、放大、鼠标拖动选中多个图形成果等### 5. shape  文件夹下蕴含了常见的形态、正方形、圆形、椭圆、多边形、还能够自定义各种形态、基类 mxShape  mxSwimlane 是流程图中比拟常见的一种形态:泳道,目前没有应用到,代码中有呈现相干逻辑,须要留神下### 6. layout  蕴含了解决图形展现的类,各种布局形式,树形布局、圆形布局等,临时不须要理解### 7. io  外部的序列化实现,采纳xml模式,目前已实现了json格局的序列化形式,暂不须要关怀这部分### 8. editor  简略快捷键、菜单反对,这部分性能将本人实现,暂不须要关怀这部分## mxgraph架构及运行流程- mxGraph: 启动模块,负责关联外部其余模块,实现整体性能,管制画布的api都在这个模块- mxGraphView: 计算元件地位,调用mxCellRenderer渲染元件,管制整体渲染逻辑- mxGraphModel:解决mxCell属性,元件父子关系,实现撤销性能等,所有对mxCell的批改操作都由这个模块实现- mxCell: 代表一个图形元件,能够是图形,也能够是边,vertex代表元件,edge代表边- mxCellState: 依据mxCell中的地位,计算出的实在地位保留在这个模块- mxConnectionHandler: 负责2个元件之前的连接线,自带的鼠标hover连接点成果- mxGraphHandler: 元件选中成果- mxVertexHandler: 元件resize成果- mxRubberband: 鼠标按住左键,批量选中成果- mxPanningHandler: 鼠标按住右键拖动画布成果- mxEdgeHandler:连接线挪动,扭转线段地位- mxCellMarker: 元件高亮成果- mxPerimeter: 计算元件的边缘,用来计算连接线的起始点地位和起点地位- mxGeometry: 坐标、宽度、高度,用于mxCell,relative属性示意绝对于父容器布局,区间为0-1,[0,0]代表父容器左上角,[1,1]代表父容器右下角- mxGuide:元件和其余元件呈现程度或垂直对齐时,将呈现对齐线段- mxConstraintHandler: 框架内置的元件连接点,目前没有应用这个性能,不满足需要- mxUndoManager:配合mxGraphModel、mxUndoableEdit实现撤销性能>其中很多模块都继承了mxEventSource,以实现公布订阅模式,外部也十分多的应用了这个模式。比方mxGraphView监听鼠标事件,而后告诉所有的handler解决这些事件,以实现对应的交互成果。每次增加元件、删除元件、撤销操作、挪动,都会触发对应的事件,内部只须要监听对应模块的对应事件,就能够做一些非凡判断等。### 次要流程:1. mxGraph初始化,生成外部实例mxGraphView、mxGraphModel、各种须要的handler等2. mxGraph调用mxGraphView初始化dom容器,mxGraphView绑定鼠标点击事件,并生成背景网格3. 触发内部事件:     3.1 内部增加、删除元件,调用mxGraph.importCells、removeCells等办法,触发mxGraphModel批改mxCell属性,而后告诉mxGraphView从新渲染整个画布,从新计算mxCellState,调用mxCellRenderer渲染单个元件     3.2 鼠标选中等事件,mxGraphView监听鼠标事件,告诉对应的handler模块,handler模块调用mxGraph模块,mxGraph告诉mxGraphModel批改mxCell属性,从新渲染  ### 撤销性能实现原理:- mxGraphModel有2个应用频率很高的api,beginUpdate和endUpdate,各个demo中都应用了这2个api,能够嵌套应用,用来记录一次操作,以反对撤销。  - 因为mxCell保留了画布所有元件,每次新增元件、挪动地位操作都将通过mxGraphModel生成一个mxUndoableEdit对象,外面保护了多个批改操作,由各种Change组成,model文件夹下的各个Change模块是理论执行撤销操作的,外部保护了previous属性,用来进行撤销操作。## mxgraph 罕用函数、属性、style属性1. mxGraph  代表一个画布实例,能够对画布放大、放大、挪动、撤销、  应用到的办法介绍:    - insertVertex: 插入元件    - insertEdge: 插入连接线    - setPanning:反对按住鼠标右键挪动    - groupCells:将元件封装成一个新的元件    - cellsAdded:当新的元件增加到画布时触发    - translateCell:挪动指定元件    - resizeCell: 缩放元件    - getBoundingBoxFromGeometry:获取指定元件组成的范畴大小    - center: 将画布地位居中显示    - setCellStyles: 给元件设置新的款式,扭转元件色彩,宽低等    - zoomIn: 放大画布    - zoomOut: 放大画布2. mxCellRenderer    - redrawLabel: 控制元件的label是否显示    - isShapeEvent: 管制是否响应元件的事件    - redraw: 从新渲染单个元件3. mxConnectionHandler    - connect:将2个元件连贯在一起4. mxGraphView    - validate:从新渲染画布    - validateCellState: 从新计算元件的实在宽高    - getPerimeterPoint: 计算连接点的起始点、起点地位5. mxGraphModel(这个模块的函数次要由mxGraph调用)    - cloneCells: clone元件    - remove: 删除元件    - add: 增加元件    - setVisible: 设置是否可见    - beginUpdate: 开始一个事物(撤销性能)    - endUpdate: 完结一个事物(撤销性能)6. mxCellMarker(援用mxCellHighlight实现高亮成果)   - process: 解决鼠标事件,判断是否高亮元件   - intersects: 判断鼠标是否在元件的核心7. mxCell(代表一个图形,包含元件和连接线)   - value: 元件的label值   - style: 以后图形的款式   - vertex: 是否是元件   - edge: 是否是连接线   - children: 列表,以后图形的子图形元件style属性列表,不同元件会有本人的公有属性,上面是通用的一些属性1. width 元件宽度2. height 元件高度3. shape 以后元件的形态4. fillColor 元件填充色彩5. strokeColor 元件图形色彩6. align label对齐形式7. opacity 透明度8. flipH  程度翻转9. rotation  抉择角度## 开发中遇到的问题和解决方案- 源码是应用es5开发的,蕴含了很多prototype,bind函数,没有模块化语法反对等,不利于源码浏览和前期的大量扩大外部实现。   > 解决方案: 将mxgraph源码从es5转化为es6语法,增加模块化导入、删除es5中的bind函数、应用class继承代替prototype。- 批量导入svg元件,解决外部的连接点信息和元件属性   > 解决方案: 应用sax解决xml文件,获取svg外部的连接点和元件属性- 显示元件的连接点,内置的Constraint个性不合乎需要(元件挪动时,连接线会扭转地位)   > 解决方案: 通过在元件中增加子节点来实现,须要次要的是地位须要绝对于父容器定位- 文件导出,导入,框架应用xml实现,实现较简单,不好增加自定义数据   > 解决方案: 本人实现一套基于json的数据格式,将mxGraphModel中的数据保留- 封装性能,框架虽实现了一部分性能,但存在很多问题,ui地位问题,还有封装后连接点解决都须要本人实现,大部分工夫在解决封装相干问题   > 解决方案: 扩大mxGraph模块,从新了外部多个办法的实现,增加自定义解决逻辑,参考GraphWithGroup文件- 进入封装元件的撤销操作问题,内置只有一个撤销管理器   > 解决方案: 增加多个撤销管理器,进入每个字容器,生成一个新的撤销管理器- 多个元件封装后,进行撤销操作,呈现bug   > 解决方案: 还在解决中,须要深刻了解外部相干原理- 进入封装元件后,如果子元件被内部连贯,须要显示一个虚构连贯元件,并解决其地位(放弃在对应元件的左侧或右侧)   > 解决方案: 重写enterGroup,动静增加VirtualCell类型,并在解决其地位的函数中,从新计算其地位信息,并从新渲染对应的连接线- 元件序号:同一种元件名称不能反复,名称惟一,这外面须要思考:文件导入、复制,删除等场景呈现的问题   > 解决方案: 在mxGraphModel模块,当呈现须要新增元件时,动静计算下一个的须要,并将这个属性增加到对应的元件中,保障导入的时候不呈现问题-  新增模板列表: 将导出的文件导入,须要解决整体缩放,将所有元件放在一个较小的容器内,文字暗藏,勾销交互性能   > 解决方案: 新扩大一个mxgraph子类,以实现预览成果,将所有元件不可点击等- 对齐到网格: 元件4个边角须要对齐到背景网格   > 解决方案: 网格长宽是10, 所有元件的长宽都须要满足是10的倍数- 连接线和元件连接点存在空白距离   > 解决方案: 默认状况,连接线只连贯到元件的边缘,这样会导致局部元件连接点呈现空白,须要扭转mxGraphView中的getPerimeterPoint办法,让连接线连贯到元件的核心区域- 封装元件内,连接线和连接点呈现空白距离   > 解决方案: 当元件扭转长宽时,动静扭转连接点的大小- 进入封装子容器后,扭转外部元件地位,返回下级,更新内部布局   > 解决方案: 重写exitGroup,对Group子元件进行resize解决- 放大鼠标hover连接点高亮范畴,默认状况下,鼠标放在元件中心点才回高亮元件,连接点须要非凡解决   > 解决方案: mxCellMaker模块负责元件高亮个性,重写getState办法,判断是否为连接点类型,做非凡解决