JavaScript is required

渲染系统

目的与范围

渲染系统负责将图数据(节点、线和连接)转换为屏幕上显示的可视化元素。该系统同时管理基于 SVG 的 DOM 渲染与基于 Canvas 的性能渲染,协调多层视觉合成,并通过视口裁剪为大规模图优化渲染性能。

本页面提供渲染系统的架构概览。关于具体子系统的详细信息,请参见:

关于在渲染之前定位节点的布局算法,请参见布局系统。关于渲染元素上的事件处理,请参见用户交互与事件

渲染架构概览

graph TB
    subgraph "数据层"
        GraphData["RGGraphData
(nodes, lines)"] Options["RGOptionsFull
(rendering config)"] ShouldRender["shouldRenderNodes
shouldRenderLines
(viewport culling)"] end subgraph "核心渲染逻辑" With4Line["RelationGraphWith4Line
createLineDrawInfo()"] PathGen["线路径生成器
generateLineFor1/4/44/49/6/8"] JunctionCalc["_getJunctionPoint()
RGGraphMath utilities"] end subgraph "组件层" RGCanvas["RGCanvas
(container)"] RGCanvasContent["RGCanvasContent
(orchestrates rendering)"] RGNode["RGNode
(node display)"] RGLinePath["RGLinePath
(SVG path)"] RGLineText["RGLineText
(text labels)"] end subgraph "渲染模式" StandardMode["标准 SVG 渲染
(zoom >= 40%)"] EasyViewMode["EasyView Canvas
(zoom < 40%)"] end subgraph "输出层" BehindLayer["Behind 层
(background plugins)"] MainLayer["主画布
(nodes & lines)"] AboveLayer["Above 层
(overlays)"] end GraphData --> ShouldRender Options --> ShouldRender ShouldRender --> RGCanvasContent RGCanvasContent --> With4Line With4Line --> PathGen With4Line --> JunctionCalc PathGen --> RGLinePath JunctionCalc --> RGLinePath RGCanvasContent --> RGNode RGCanvasContent --> RGLinePath RGCanvasContent --> RGLineText RGCanvas --> BehindLayer RGCanvas --> MainLayer RGCanvas --> AboveLayer MainLayer --> StandardMode MainLayer --> EasyViewMode RGNode --> MainLayer RGLinePath --> MainLayer RGLineText --> MainLayer

图:整体渲染系统架构

渲染系统遵循三层架构:

  1. 数据层:图数据与配置驱动需要渲染的内容
  2. 核心逻辑:路径生成与几何计算产出渲染指令
  3. 组件层:框架特定组件渲染可视化元素

来源:packages/relation-graph-models/models/RelationGraphWith4Line.ts:1-572, packages/platforms/vue2/src/core4vue/RGLinePath.vue:1-104, packages/platforms/react/src/relation-graph/src/core4react/RGCanvas.tsx:1-114

渲染模式

系统支持两种主要渲染模式,会根据缩放级别与性能需求进行选择:

标准 SVG/DOM 渲染

默认渲染模式使用 SVG 元素绘制线条,并使用 DOM 元素绘制节点。这提供了:

  • 完整的交互能力(点击、悬停、拖拽事件)
  • 在所有缩放级别下清晰锐利的渲染效果
  • CSS 样式与动画
  • 基于插槽(slot)的自定义

使用时机:当 options.canvasZoom >= 40options.performanceMode 被禁用时。

EasyView Canvas 模式

一种性能优化模式,使用 HTML5 Canvas 2D 上下文进行渲染:

  • 面向大图的更低内存占用
  • 对数百个节点具备更快的渲染速度
  • 交互受限(通过坐标映射检测点击)
  • 在低缩放级别下自动启用

使用时机:当 options.canvasZoom < 40options.performanceMode 启用时,或通过 options.showEasyView 显式启用时。

graph LR
    ZoomCheck{"canvasZoom >= 40?"}
    PerfCheck{"performanceMode enabled?"}
    SVGRender["标准 SVG 渲染"]
    CanvasRender["EasyView Canvas"]
    
    ZoomCheck -->|Yes| SVGRender
    ZoomCheck -->|No| PerfCheck
    PerfCheck -->|Yes| CanvasRender
    PerfCheck -->|No| SVGRender

图:渲染模式选择逻辑

来源:packages/relation-graph-models/models/RelationGraphWith2Data.ts:1-125, packages/platforms/react/src/relation-graph/src/core4react/RGCanvas.tsx:22-42

组件层级结构

渲染系统通过一组框架特定组件的层级结构实现,这些组件共享通用接口:

graph TB
    RGCanvas["RGCanvas
Main container, layers, zoom/pan transform"] RGCanvasContent["RGCanvasContent
Iterates nodes/lines, applies viewport culling"] RGNode["RGNode
Individual node display"] RGLinePath["RGLinePath
SVG path for line"] RGLineText["RGLineText
Text label via teleport"] RGConnectTarget["RGConnectTarget
Connection points for drag"] RGEasyView["RGEasyView
Canvas fallback renderer"] RGCanvas --> RGCanvasContent RGCanvas --> RGEasyView RGCanvasContent --> RGNode RGCanvasContent --> RGLinePath RGCanvasContent --> RGLineText RGNode --> RGConnectTarget

图:渲染组件层级结构

组件 目的 文件位置
RGCanvas 根容器,管理图层与画布变换 vue2/RGCanvas.vue, vue3/RGCanvas.vue, react/RGCanvas.tsx, svelte/RGCanvas.svelte
RGCanvasContent 渲染过滤后的节点与线条,编排子组件 vue2/RGCanvasContent.vue, vue3/RGCanvasContent.vue, etc.
RGNode 显示单个节点,可选插槽 vue2/RGNode.vue, vue3/RGNode.vue, etc.
RGLinePath 为线条渲染 SVG <path> 元素 vue2/RGLinePath.vue, vue3/RGLinePath.vue, etc.
RGLineText 使用 teleport/portal 渲染线条文本标签 vue2/RGLineText.vue, vue3/RGLineText.vue, etc.
RGEasyView 性能模式下的基于 Canvas 的渲染器 vue2/RGEasyView.vue, vue3/RGEasyView.vue, etc.

来源:packages/platforms/vue3/src/relation-graph/src/core4vue3/RGCanvas.vue:1-86, packages/platforms/react/src/relation-graph/src/core4react/RGCanvas.tsx:1-114, packages/platforms/svelte/src/core4svelte/RGCanvas.svelte:1-89

渲染流水线

flowchart TD
    DataUpdate["Graph Data Updated
addNode(), updateLine()"] DataProvider["RGDataProvider
commits changes"] RequestFrame["_dataUpdated()
requestAnimationFrame"] ViewportCulling["updateShouldRenderGraphData()
filters visible items"] RenderCheck{"Rendering Mode?"} SVGPath["SVG Rendering Path"] CanvasPath["Canvas Rendering Path"] CreateLineInfo["createLineDrawInfo()
RelationGraphWith4Line"] GeneratePath["generateLinePath()
withLineJunctionPoints()"] PathCalculation["createLinePathData()
generateLineFor1/4/44/49/6/8"] ComponentRender["Component Render
RGLinePath, RGNode"] CanvasRender["Canvas 2D Context
drawImage(), fillRect()"] DOMUpdate["DOM Updated
Browser paints"] DataUpdate --> DataProvider DataProvider --> RequestFrame RequestFrame --> ViewportCulling ViewportCulling --> RenderCheck RenderCheck -->|Standard| SVGPath RenderCheck -->|EasyView| CanvasPath SVGPath --> CreateLineInfo CreateLineInfo --> GeneratePath GeneratePath --> PathCalculation PathCalculation --> ComponentRender ComponentRender --> DOMUpdate CanvasPath --> CanvasRender CanvasRender --> DOMUpdate

图:渲染流水线流程

流水线关键阶段

  1. 数据更新:应用调用 addNodes(), updateNode(), addLines() 等方法
  2. 数据提供者:变更被批处理并提交到响应式状态
  3. 帧请求_dataUpdated() 调度一个 requestAnimationFrame 回调
  4. 视口裁剪updateShouldRenderGraphData() 基于画布偏移与视口大小过滤可见项
  5. 模式选择:根据缩放与设置选择标准 SVG 或 EasyView canvas
  6. 路径生成:对于线条,RelationGraphWith4Line 生成 SVG 路径数据
  7. 组件渲染:框架组件使用响应式数据进行渲染
  8. 浏览器绘制:原生浏览器渲染完成该帧

来源:packages/relation-graph-models/models/RelationGraphWith4Line.ts:80-114, packages/relation-graph-models/models/RelationGraphWith7Event.ts:1-870

线条渲染概览

线条以 SVG <path> 元素渲染,并支持多种形状:

线条形状 代码值 描述 生成函数
直线 1 从起点到终点的直接连线 generateLineFor1()
简单正交 4 基本直角连接 generateLineFor4()
标准正交 44 具备多个分段的智能正交 generateLineFor44()
硬正交 49 用户可调整的正交分段 generateLineFor49()
标准曲线 6 贝塞尔曲线连接 generateLineForCurve6()
曲线变体 2, 3, 5, 7 不同的曲线样式 generateLineForCurve()
特殊曲线 8 另一种曲线算法 generateLineFor8()

线条渲染过程:

  1. 连接点计算:确定线条与节点边界连接的位置
  2. 路径生成:基于线条形状生成 SVG 路径命令
  3. 文本定位:计算文本标签的位置与旋转角度
  4. 箭头标记:应用 SVG marker 作为箭头
graph LR
    Link["RGLink
(fromNode, toNode)"] Line["RGLine
(style, shape)"] CreateInfo["createLineDrawInfo()"] WithJunction["withLineJunctionPoints()"] GetJunction["_getJunctionPoint()"] CreatePath["createLinePathData()"] PathInfo["RGLinePathInfo
(pathData, textPosition)"] Component["RGLinePath Component"] Link --> CreateInfo Line --> CreateInfo CreateInfo --> WithJunction WithJunction --> GetJunction WithJunction --> CreatePath CreatePath --> PathInfo PathInfo --> Component

图:线条渲染数据流

关于线条路径生成与连接点计算的详细信息,请参见线渲染系统连接点(Junction Points)与路径计算

来源:packages/relation-graph-models/models/RelationGraphWith4Line.ts:27-571, packages/platforms/vue2/src/core4vue/RGLinePath.vue:1-104, packages/platforms/react/src/relation-graph/src/core4react/RGLinePath.tsx:1-77

节点渲染

节点以 DOM 元素(通常为 <div> 元素)渲染,并在画布内以绝对定位方式放置:

关键节点属性

  • 位置node.x, node.y(画布坐标)
  • 尺寸node.width/node.el_W, node.height/node.el_H
  • 形状node.nodeShape(0=circle, 1=rect,默认来自 options)
  • 样式node.color, node.fontColor, node.borderColor, node.borderWidth

节点变换计算

style.transform = `translate(${node.x}px, ${node.y}px)`
style.width = `${node.el_W}px`
style.height = `${node.el_H}px`

节点可通过以下方式自定义:

  • 插槽内容:替换默认节点渲染
  • CSS 变量--rg-node-color, --rg-node-border-color, etc.
  • 节点专属样式node.cssVars 对象

连接目标:每个节点都可以显示用于交互式创建连线的连接点(RGConnectTarget)。这些连接点位于特定的连接位置(上、右、下、左、中)。

来源:packages/relation-graph-models/models/RelationGraphWith7Event.ts:80-190

多层渲染系统

画布使用三层架构以支持灵活的 z 轴顺序:

graph TB
    Container["RGCanvas Container"]
    
    subgraph "图层堆栈(从下到上)"
        BackgroundSlot["背景插槽
(grid, watermark)"] BehindLayer["Behind 层
canvas-plug-behind slot"] MainCanvas["主画布
(nodes & lines)"] AboveLayer["Above 层
canvas-plug-above slot"] end Container --> BackgroundSlot Container --> BehindLayer Container --> MainCanvas Container --> AboveLayer MainCanvas --> Nodes["已渲染节点"] MainCanvas --> Lines["已渲染线条"]

图:多层画布架构

图层用途

图层 用途 CSS 类名 是否应用 Transform
背景 静态背景内容 .rg-map-background
Behind 图内容下方的自定义内容 .rg-canvas-slot-behind 是(zoom/pan)
主层 节点与线条 .rg-map-canvas 是(zoom/pan)
Above 覆盖层(工具提示、控件) .rg-canvas-slot-above 是(zoom/pan)

除 Background 外的所有图层共享同一变换:

transform: translate(${canvasOffset.x}px, ${canvasOffset.y}px) 
           scale(${canvasZoom / 100}, ${canvasZoom / 100})

这确保缩放与平移操作会一致地影响所有图内容,同时保持背景静止不动。

来源:packages/platforms/vue3/src/relation-graph/src/core4vue3/RGCanvas.vue:36-83, packages/platforms/react/src/relation-graph/src/core4react/RGCanvas.tsx:58-110, packages/platforms/svelte/src/core4svelte/RGCanvas.svelte:36-88

视口裁剪与性能

渲染系统实现了视口裁剪,以避免渲染屏幕外元素:

裁剪机制

  1. updateShouldRenderGraphData() 计算可见视口边界
  2. 过滤节点:只有处于视口 + 边距范围内的节点才会加入 shouldRenderNodes
  3. 过滤线条:只有连接可见节点的线条才会加入 shouldRenderLines
  4. 组件仅遍历已过滤集合

性能收益

  • 为大图(1000+ 节点)减少 DOM 元素数量
  • 在平移/缩放操作期间维持 60fps
  • 随视口变化自动调整

EasyView Canvas 模式: 当启用性能模式且缩放低于 40% 时,系统会:

  • 禁用精细的 SVG 渲染
  • 将简化表示渲染到 canvas
  • 通过坐标映射维持交互能力

关于详细的性能优化技术,请参见性能模式与 EasyView

来源:packages/relation-graph-models/models/RelationGraphWith2Data.ts:31-110, packages/relation-graph-models/models/RelationGraphWith7Event.ts:332-338

框架特定实现

每个平台(Vue2、Vue3、React、Svelte)以各自框架特有的模式实现相同的渲染架构:

Vue 2 & 3:使用基于模板的组件与插槽

  • 响应式:Vue 的响应式数据系统(refs/reactive)
  • 插槽<slot name="node">, <slot name="line">
  • Teleport:使用 <teleport> 定位线条文本

React:使用 JSX 组件与 render props

  • 响应式useStateuseGraphStore 自定义 hook
  • Children:render prop 函数或 React nodes
  • Portal:使用 createPortal() 定位线条文本

Svelte:使用 Svelte 组件与插槽

  • 响应式:Svelte stores(writable
  • 插槽<slot name="node">, <svelte:fragment>
  • Portal:用于线条文本的自定义 portal action

所有实现通过 types 包中定义的共享 TypeScript 接口保持 API 兼容性。

来源:packages/platforms/vue2/src/core4vue/RGLinePath.vue:59-100, packages/platforms/vue3/src/relation-graph/src/core4vue3/RGLinePath.vue:1-91, packages/platforms/react/src/relation-graph/src/core4react/RGLinePath.tsx:1-77, packages/platforms/svelte/src/core4svelte/RGLinePath.svelte:1-84

总结

渲染系统通过以下方式将图数据转换为可视化输出:

  1. 双渲染模式:标准 SVG 追求质量,Canvas 追求性能
  2. 基于组件的架构:框架特定实现共享核心逻辑
  3. 多层合成:为插件与覆盖层提供灵活的 z 顺序
  4. 视口裁剪:面向大图的性能优化
  5. 路径生成:支持多种线条形状与连接点类型

该系统旨在在不同规模与用例下平衡视觉质量、交互性与性能。