DiagramJS设计原理解读(二)
DiagramJS(一)
 Diagram.js 是一个基于依赖注入的图表/图形库核心组件,它使用 didi 库来实现模块化和依赖管理
核心模块包括:Canvas(创建和管理SVG画布)、ElementFactory(创建元素)、ElementRegistry(注册和管理元素)、GraphicsFactory(创建SVG结构)、EventBus

渲染流程
1. 初始化流程:
- Diagram创建时,初始化核心模块(Canvas、EventBus、ElementRegistry、GraphicsFactory等)
- Canvas创建SVG容器和视口
- 触发diagram.init事件,通知所有模块初始化完成
2. 元素创建流程:
- 通过ElementFactory创建元素模型(shape或connection)
- 调用Canvas的addShape或addConnection方法
- ElementRegistry注册元素与其图形表示的映射关系
- GraphicsFactory创建元素的SVG容器结构(djs-group> djs-element> djs-visual)
3. 元素渲染流程:
- GraphicsFactory调用drawShape或drawConnection方法
- 通过EventBus触发render.shape或render.connection事件
- DefaultRenderer(或自定义渲染器)响应事件,执行具体的绘制逻辑
- 创建的SVG元素被添加到djs-visual容器中
4. 元素更新流程:
- 当元素属性变更时,调用GraphicsFactory.update方法
- 清除现有的视觉元素
- 重新调用绘制方法
- 更新元素位置(对于shape类型)
5. 交互事件处理:
- InteractionEvents模块监听DOM事件
- 将DOM事件转换为diagram-js事件(如element.click)
- 通过EventBus分发事件
- 相关模块响应事件,执行相应操作
  
  
  
  
GraphicsFactory
创建
SVG容器结构,负责图形元素的创建(create)和更新(update),管理元素的层次结构,触发渲染事件(render.shape、render.connection)
绘制逻辑drawShape和drawConnection,触发事件总线,Renderer负责具体绘制逻辑
核心功能说明
- 图形工厂初始化
- 依赖EventBus进行事件通信
- 依赖ElementRegistry管理元素注册信息
- 容器创建流程
- 创建最外层group容器(djs-group)
- 创建元素容器(djs-element)
- 创建视觉容器(djs-visual)
- 根据类型添加特定样式(djs-shape/djs-connection)
- 元素管理机制
- 维护父子层级关系
- 处理元素定位和更新
- 支持元素的添加、更新和删除
- 渲染机制
- 通过EventBus触发渲染事件
- 支持形状和连接线的差异化渲染
- 提供路径计算和图形绘制接口
Render
实现
具体的绘制逻辑,处理形状和连接线的绘制

 
- canRender :DefaultRenderer总是返回true,确保它能处理任何元素
- drawShape :创建矩形SVG元素,应用样式,并添加到视觉容器
- drawConnection :创建连接线SVG元素,应用样式,并添加到视觉容器
- getShapePath :计算形状的SVG路径字符串
- getConnectionPath :计算连接线的SVG路径字符串
渲染器继承结构
DefaultRenderer继承自BaseRenderer,采用了优先级机制确保默认渲染器只在没有其他渲染器能处理元素时才会被调用。DefaultRenderer的优先级被设置为最低(1),而BaseRenderer的默认优先级为1000。
渲染器初始化
DefaultRenderer在初始化时:
- 调用父类BaseRenderer的构造函数,传入eventBus和优先级
- 定义三种样式: - CONNECTION_STYLE:连接线样式(洋红色,宽度5px)
- SHAPE_STYLE:形状样式(白色填充,洋红色边框)
- FRAME_STYLE:框架样式(无填充,虚线边框)
 
渲染流程
整个渲染流程由以下组件协同完成:
- Canvas :提供绘图容器和视口管理
- EventBus :处理渲染事件的分发
- ElementRegistry :管理元素和图形的映射关系
- GraphicsFactory :创建SVG图形元素
- Renderer :实际执行绘制操作
形状绘制流程
- GraphicsFactory接收到绘制请求
- 通过EventBus触发'render.shape'事件
- BaseRenderer监听该事件并根据优先级调用合适的渲染器
- DefaultRenderer的drawShape方法创建矩形SVG元素
- 根据元素类型应用不同样式
- 将创建的SVG元素添加到视觉容器(GraphicFactory管理)中
连接线绘制流程
- GraphicsFactory接收到绘制请求
- 通过EventBus触发'render.connection'事件
- BaseRenderer监听该事件并根据优先级调用合适的渲染器
- DefaultRenderer的drawConnection方法创建多段线SVG元素
- 使用RenderUtil.createLine方法根据路径点创建线条
- 应用CONNECTION_STYLE样式
- 将创建的SVG元素添加到视觉容器中
路径计算
DefaultRenderer还提供了两个重要方法来计算SVG路径:
- getShapePath:计算形状的SVG路径,- 创建一个矩形路径
- getConnectionPath:计算连接线的SVG路径,- 根据路径点创建一个连续线段
Canvas & SVG &Renderer
Canvas
- 定义:Canvas 是 HTML5 提供的用于绘制图形的元素,通过 JavaScript 可以动态地绘制图形。
- 常见问题:如何在 Canvas 上绘制基本图形(如矩形、圆形)、如何处理图像、如何实现动画效果。
- 回答示例:Canvas 提供了一个 2D 绘图上下文,可以使用 getContext('2d')方法获取,通过调用绘图上下文的方法来绘制图形。
SVG
- 定义:SVG 是一种基于 XML 的矢量图形格式,适用于在网页中展示高质量的图形。
- 常见问题:SVG 与 Canvas 的区别、如何在 SVG 中创建和操作图形元素、如何使用 CSS 和 JavaScript 操作 SVG。
- 回答示例:SVG 是基于矢量的,适合绘制需要缩放的图形,而 Canvas 是基于像素的,适合绘制需要频繁更新的图形。
Renderer
- 定义:在图形库中,Renderer 通常指负责将数据渲染为可视图形的组件。
- 常见问题:如何实现自定义渲染器、渲染器的生命周期、如何优化渲染性能。
- 回答示例:渲染器通常通过监听事件来决定何时更新图形,通过优化绘制路径和减少重绘次数来提高性能。
自定义Renderer
要自定义一个renderer,首先需要理解diagram.js中的渲染机制。diagram.js采用模块化设计,通过事件总线(EventBus)协调各个模块的交互。自定义renderer需要继承BaseRenderer,并实现canRender、drawShape、drawConnection等方法。可以通过事件监听机制,在特定的渲染事件中调用自定义的绘制逻辑。通过这种方式,可以灵活地扩展和定制图形的渲染行为,满足特定的业务需求。
diagram.js 设计思路
- 模块化设计:diagram.js 采用模块化设计,通过依赖注入系统管理各个组件,确保松耦合和高可扩展性。
- 事件驱动:使用 EventBus 处理渲染事件,协调Canvas、GraphicsFactory 和 Renderer的交互。
- 渲染流程:Canvas 管理 SVG 画布,GraphicsFactory 创建和更新图形元素,DefaultRenderer 实现具体的绘制逻辑。


