sigma.js v2 与 v1 版本 API 差异及迁移指南

作者:微光

时间:2026-10-30

浏览:592

深入解析 sigma.js v2 与 v1 的核心架构变迁、API 映射关系、数据模型解耦与交互模式重构,提供从 v1 平滑迁移至 v2 的完整实操步骤、对照示例与踩坑指南。

文章目录

sigma.js 从 v1 到 v2 并不是一次常规的功能迭代,而是一次底层架构的完全重写。核心变化是图数据模型完全解耦并转交由独立的 graphology 库驱动,渲染引擎全面转向纯 WebGL 高性能流水线,同时 API 全面适配现代 ES Module 与 TypeScript 生态。本文梳理两个版本在架构、数据模型、事件与样式机制上的核心差异,并提供详细的 API 对照与逐步迁移指南。

sigma.js v2 与 v1 版本 API 差异及迁移指南
图 0:sigma.js v1 与 v2 核心技术演进全览

一、核心架构与设计理念的本质变化

在评估是否升级或准备迁移前,必须先理解 v2 为何做出根本性重构。在 sigma.js v1 时代,框架承担了“全包管家”的角色:它不仅负责在浏览器窗口中绘制圆圈和连线,还自己维护了一套图的数据结构(s.graph),并打包了旧式的 Canvas 渲染逻辑和全局插件机制。

这种设计在图规模达到数千个节点时就会遇到明显的性能瓶颈,且由于图操作逻辑被封装在渲染器内部,外部应用很难将图数据与 React、Vue 等现代状态管理体系深度结合。为此,v2 进行了彻底的“职责剥离”:

  • 数据层完全交还社区标准:sigma.js 不再负责维护图的拓扑数据结构,而是完全依赖 graphology。所有节点的增删、属性变更、邻接点查询与图算法均由 graphology 提供。
  • 渲染层专注高性能 WebGL:放弃了旧版维护成本高且性能受限的 2D Canvas 主渲染器,v2 的核心是一个高度优化的纯 WebGL 渲染引擎,节点与边的几何顶点通过着色器在 GPU 中并行绘制。
  • 样式驱动转为声明式 Reducer:v1 中若要高亮某个节点,必须遍历图数据直接改写 node.color 并调用 s.refresh();v2 引入了类似于前端状态管理的 nodeReducer 与 edgeReducer,在不污染底层图数据的前提下动态返回渲染态样式。
sigma.js v2 与 v1 版本 API 差异及迁移指南
图 1:sigma.js v1 与 v2 架构分工与职责转移对比

二、关键 API 与语法差异对比

迁移过程中最常碰到的就是 API 命名与调用语境的改变。下表列出了 v1 核心方法在 v2 中的直接对标方式:

功能模块 sigma.js v1 语法 sigma.js v2 语法
类与构造函数 new sigma({ graph, container }) 或 new sigma('container-id') new Sigma(graph, container, [options])(注意首字母大写)
数据载体 s.graph (内置专用类) graphology.Graph (需单独实例化传入)
添加节点 s.graph.addNode({ id, label, x, y, size }) graph.addNode(id, { label, x, y, size })(id 分离为第一个参数)
添加边 s.graph.addEdge({ id, source, target }) graph.addEdgeWithKey(id, source, target, attr) 或 graph.addEdge(s, t, attr)
相机与视角控制 s.cameras[0].goTo({ x, y, ratio }) renderer.getCamera().setState({ x, y, ratio })
事件监听 s.bind('clickNode', fn),参数为 e.data.node renderer.on('clickNode', fn),参数为 { node, event, ... }
动态高亮样式 修改节点对象 n.color = '#f00' 并执行 s.refresh() 配置 nodeReducer 纯函数返回渲染态属性
力导向布局 s.startForceAtlas2(config) new FA2Layout(graph, config).start() (来自独立包)
实例销毁 s.kill() renderer.kill() (或 graph.clear() 清空图)
sigma.js v2 与 v1 版本 API 差异及迁移指南
图 2:常用图操作在 v1 与 v2 中的直接对标逻辑

三、分步迁移实操指南

对已有 v1 项目进行重构时,建议按照“依赖替换 → 数据结构迁移 → 渲染层绑定 → 交互与样式重构 → 布局迁移”的顺序逐步推进,避免多处破坏性变更同时交织导致难以排查问题。

sigma.js v2 与 v1 版本 API 差异及迁移指南
图 3:sigma.js v1 到 v2 的系统化迁移四步操作流

第 1 步:依赖管理与工程环境清理

在项目中移除旧版本的 sigma 库及附属插件,并安装 sigma v2 及其核心依赖 graphology。如果使用了力导向布局,还需要安装对应算法包:

# 卸载旧版依赖
npm uninstall sigma

# 安装 v2 核心渲染库及图模型
npm install sigma@^2.4.0 graphology@^0.25.4

# 若需要 ForceAtlas2 布局支持,安装对应 graphology 扩展
npm install graphology-layout-forceatlas2@^0.10.1

第 2 步:重写图数据生成与属性绑定

在 v1 中,节点数据通常是一个包含 id 的对象,且经常直接丢进 graph.read({ nodes, edges })。在 v2 中,必须先构建 Graphology 实例。另外需要特别注意:每个节点必须明确具备 x、y、size 和 color 属性,WebGL 着色器依赖这些数值计算顶点缓冲区;如果缺少 x 或 y,渲染器会抛出异常或无法呈现。

// ==================== v1 做法 ====================
var s = new sigma('container');
s.graph.read({
  nodes: [
    { id: 'n1', label: '节点 A', x: 0, y: 0, size: 5, color: '#6487A5' },
    { id: 'n2', label: '节点 B', x: 10, y: 10, size: 5, color: '#C28B68' }
  ],
  edges: [
    { id: 'e1', source: 'n1', target: 'n2', size: 1, color: '#CCCCCC' }
  ]
});
s.refresh();

// ==================== v2 迁移后 ====================
import Graph from 'graphology';

const graph = new Graph();

// 添加节点:第一个参数为唯一 Key/ID,第二个参数为属性字典
graph.addNode('n1', {
  label: '节点 A',
  x: 0,
  y: 0,
  size: 10,
  color: '#6487A5'
});

graph.addNode('n2', {
  label: '节点 B',
  x: 1,
  y: 1,
  size: 10,
  color: '#C28B68'
});

// 添加边:可以使用 addEdgeWithKey 显式指定边 ID,或由系统自动生成
graph.addEdgeWithKey('e1', 'n1', 'n2', {
  size: 2,
  color: '#CCCCCC'
});

避坑提示:坐标系差异
v1 的渲染引擎会自动根据容器大小进行宽松的缩放和中心对齐;而 v2 基于 WebGL 坐标系,更倾向于使用归一化坐标或比例较为平衡的数值范围(例如 [0, 1] 或 [-100, 100])。如果原有数据的坐标跨度极大(如数万像素),请在录入前进行一次归一化处理,或通过相机初始化配置来适配视口。

第 3 步:重构渲染器实例化与事件绑定

v2 统一采用 new Sigma(graph, container, [options]),首字母必须大写。同时,事件绑定由 bind() 变为标准的 on(),事件回调的载荷(payload)由包含深层嵌套的 e.data 简化为展开后的事件上下文:

// ==================== v1 事件与相机 ====================
s.bind('clickNode', function(e) {
  var clickedNodeId = e.data.node.id;
  console.log('点击节点:', clickedNodeId);
});

// 相机定位移动
s.cameras[0].goTo({ x: 0, y: 0, ratio: 0.5 });

// ==================== v2 迁移后 ====================
import Sigma from 'sigma';

const container = document.getElementById('container');
const renderer = new Sigma(graph, container, {
  renderEdgeLabels: true,
  allowInvalidContainer: false
});

// 事件监听:结构解构更直接
renderer.on('clickNode', ({ node, event }) => {
  console.log('点击节点 key:', node);
  console.log('原始 DOM 事件:', event);
});

// 相机控制:通过专用 Camera 实例操作
const camera = renderer.getCamera();
camera.setState({
  x: 0.5,
  y: 0.5,
  ratio: 0.5,
  angle: 0
});
// 也可以调用动画重置:camera.animatedReset();

第 4 步:动态样式重构——使用 Reducer 替代破坏性改值

在图分析应用中,最常见的交互是“悬停(Hover)或点击某个节点时,将其邻居高亮,其余节点暗化”。在 v1 中,通常是通过循环遍历所有节点,临时将非邻居节点的 color 改为浅灰,最后调用 s.refresh()。这种方式不仅破坏了原本的真实业务数据,而且在大图频繁触发时会造成严重的性能卡顿。

v2 引入了 Node Reducer 与 Edge Reducer 模式。Reducer 是纯函数,负责在每一帧渲染时决定某个节点在当前状态下的视觉属性(如颜色、大小、隐藏与否),完全不改写 Graph 存储的底层数据:

// 当前选中的焦点节点 ID
let hoveredNode = null;

// 设置节点样式 Reducer
renderer.setSetting('nodeReducer', (node, data) => {
  const res = { ...data };

  // 若存在激活节点
  if (hoveredNode) {
    if (node === hoveredNode) {
      res.color = '#C28B68'; // 选中节点高亮强调色
      res.size = data.size * 1.3;
      res.highlighted = true;
    } else if (graph.areNeighbors(node, hoveredNode)) {
      res.color = '#6487A5'; // 邻接节点保持主色
      res.highlighted = false;
    } else {
      res.color = '#E5E7EB'; // 非关联节点灰度暗化
      res.label = '';         // 隐藏无关文本
    }
  }

  return res;
});

// 监听鼠标移入与移出,直接触发轻量渲染,无需遍历改写图数据
renderer.on('enterNode', ({ node }) => {
  hoveredNode = node;
  renderer.refresh(); // 仅通知渲染层重新执行 Reducer,极速轻量
});

renderer.on('leaveNode', () => {
  hoveredNode = null;
  renderer.refresh();
});

第 5 步:布局计算(ForceAtlas2)迁移

在 v1 中,ForceAtlas2 作为一个内置插件挂载在 sigma 实例上:s.startForceAtlas2()。在 v2 中,布局算法独立为一个单独的运算工具,支持同步迭代计算,也支持在 Web Worker 线程中后台运行:

// ==================== v1 布局 ====================
s.startForceAtlas2({
  worker: true,
  barnesHutOptimize: true,
  iterationsPerRender: 2
});
// 稍后停止
s.stopForceAtlas2();

// ==================== v2 迁移后 ====================
import FA2Layout from 'graphology-layout-forceatlas2/worker';

// 实例化布局 Worker,将 graph 实例传入
const layout = new FA2Layout(graph, {
  settings: {
    barnesHutOptimize: true,
    gravity: 1,
    scalingRatio: 2
  }
});

// 启动后台计算(不阻塞 UI 主线程)
layout.start();

// 当需要停止时
// layout.stop();

// 也可以监听计算步进事件(可选)

四、常见问题排查与注意事项

1. 控制台报错:“Node X does not have an 'x' coordinate”
原因:v2 要求所有节点在加入 Graphology 时必须含有 x 和 y。如果导入的 JSON 数据未经过布局预计算,请先调用 graphology-layout/random 或 circular 等轻量布局赋予初始坐标,再挂载到 Sigma 渲染器中。

2. 文本标签(Label)显示截断或无法展示中文字符
原因:v2 默认将非激活态的文字渲染委托给 Canvas 覆盖层(或 WebGL 字体纹理)。若要展示中文,应在 Sigma 初始化选项中明确指定系统字体回退链,例如:
{ labelFont: '"PingFang SC", "Microsoft YaHei", sans-serif', labelSize: 12 }。

3. 原有的自定义节点形状(如星形、饼图、图片节点)失效
原因:v1 基于 2D Canvas 的 canvas.nodes.custom.js 绘制 API 无法直接在 v2 中运行。v2 中实现自定义形状需要编写继承自 NodeProgram 的 WebGL 着色器程序,或使用社区提供的 @sigma/node-image 等现成扩展包。

sigma.js v2 与 v1 版本 API 差异及迁移指南
图 4:版本能力对比与迁移投产自查清单

五、总结

从 sigma.js v1 迁移到 v2 的实质,是将图应用从传统的“单体 DOM/Canvas 插件”转换为“标准拓扑数据模型(Graphology)+ GPU 硬件加速渲染管线(Sigma v2)”的现代化技术架构。尽管构造方式与事件交互有破坏性调整,但随着职责边界的彻底理清,不仅解决了数万量级图节点的流畅交互难题,也使得状态管理、算法拓展与组件化封装变得更为健壮可维护。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章