乐趣区

关于javascript:mxgraph学习参考文档


## 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 等简单的带快捷键、工具栏,菜单性能的 demo

mxgraph 能兼容 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 办法,判断是否为连接点类型,做非凡解决
退出移动版