前言
Meta2d.js 是一个国产开源的 2D 可视化引擎,用来快速搭建 Web 组态、SCADA、监控大屏、流程图、中控可视化以及图形编辑与交互等应用 —— 接入实时数据,设置动画和条件,画面实时自动更新,还支持绘制、编辑、交互。Meta2d.js以「数据驱动显示」的理念服务了大量工业与物联网项目,1.0 的性能表现已经足够能打。而今历时一年自我革命,全新重构重写 —— 渲染管线、事件拾取、动画系统、数据通信,每一层都推倒重来,只为让性能更上一层楼、让多人协作从无到有。
一、Meta2d.js是什么
Meta2d.js 是一个开源的2D 可视化引擎,核心是「数据驱动显示 + 动态交互」:
- 数据变化,驱动画面实时变化
- 条件、交互、消息、事件的即时响应
典型使用场景
-
工业组态 / SCADA:电力、水务、能源、工厂产线监控,设备点位、管线、告警联动;
-
监控大屏 / 中控可视化:智慧楼宇、机房动环、交通调度,动图与实时数据同屏;
-
流程图 / 架构图编辑器:拓扑图、ER 图、组织架构,自带编辑交互开箱即用;
-
报表 / 数据可视化:实时数据驱动的大屏报表;
-
可视化产品底座:MIT 协议,基于它二次开发自己的设计器 / 编辑器。
二、AI 时代的可视化底座
Meta2d.js 2.0 不内置 AI 模型,却天然对 AI 友好:
-
数据驱动,输出即渲染
引擎的核心是「数据 + 算法 + 风格 = 栩栩如生」,本质上就是一份结构化 JSON。AI生成可视化数据后,引擎即刻显示 —— 实现「AI 生成 → 可视化」即时呈现。
-
支持生成式、渐进式体验
可以很方便的支持 AI 生成式、渐进式的数据可视化展示。
-
性能扎实,支持海量图元
AI 一次性生成10万、100万+节点都能即时显示、流畅运行。
-
人机同屏协作,改动可追溯
多人协作不止于人 —— AI Agent 也可以作为协作者实时增删改画布。差量 patch 让每一次 AI 改动都可同步、可回放、可追溯;五通道实时数据管道 + 数据点绑定,让 AI 推理结果、设备数据直接驱动画面联动。
一句话:AI 负责 "生成",Meta2d 负责 "渲染、交互、协作" —— 这就是 AI 时代可视化底座该有的样子。
三、性能强劲,百万图元依旧实时联动
性能基准测试: 基于官方压力与性能基准测试(examples/benchmark)
测试环境: 8核 3.8GHz CPU,32GB 内存
| 图元 | 性能:帧 | 性能:内存(MB) | 备注 |
|---|---|---|---|
| 1万 | 117 - 120 | 44 - 50 | 拖拽、缩放不影响 |
| 10万 | 114 - 120 | 80 - 110 | 鼠标拾取不掉帧 |
| 100万 | 109 - 117 | 510 - 840 | 鼠标拾取不掉帧 |
注:200 图片、2000 数据点、400 动画 都一样,没有再额外设置
10万图元,缩放网页以便容纳所有图元,画布不缩放
10万图元,不缩放网页,缩放画布
100万图元,不缩放网页,缩放画布
性能优化小过程:原计划2026年9月25号中秋节前发版2.0。我们测试大概10万图元是流畅的,真实生产案例中足以满足的。但是我们开发是基于“架构 -> 设计实现”的模式编写,性能优化原计划在发布后。恰逢 claude 5.5 和 gpt 6 发布,我们决定抱着尝试的态度让AI帮我们做深度性能优化,此前都是我们工程师凭着过去5年累积的经验去设计新的架构,有点担心AI“改乱”我们的代码。我们惊喜的是AI的评估和我们大致一致,并且优化改动的代码我们可接受。于是我们决定让AI帮我们做深度性能优化后发布,因为又需要大量的审核和测试,导致发布的延后,但优化后的性能确实超出我们预期。
AI分析:
meta2d 每个动画图元各自算脏区 → 各自 postMessage → 渲染 worker 各自 clip+clear+重绘;hover worker 还各自全屏清空重绘 N(动画图元数)× 2meta2d 的单个原语实现(脏矩形、空间网格、Worker 分线程、样式 diff)都是对的,但帧内没有聚合层,所以复杂度是 O(动画图元数) 次独立重绘管线,而不是 O(1) 次。2 万图元时哪怕只有 200 个在动,也是每帧 400 次消息 + 400 次 clip/clear/draw + 400 次全屏 overlay 重绘。
四、与 Konva.js、Fabric.js、PixiJS 等绘图库的不同
都是优秀的 Canvas 技术栈,但定位完全不同:Konva / Fabric / Pixi 是 "画布基础能力" 提供者,Meta2d 是 "业务开箱即用" 的可视化引擎。
| 维度 | Meta2d.js 2.0 | Konva.js | Fabric.js | PixiJS |
|---|---|---|---|---|
| 定位 | 业务级 2D 可视化引擎 | 通用 Canvas 绘图交互库 | Canvas 对象模型库 | 高性能 2D 渲染引擎 |
| 核心卖点 | 数据驱动显示,开箱即用 | 图形绘制与交互(拖拽 / 缩放 / 事件) | 对象模型与序列化(JSON/SVG 互转) | 渲染性能(WebGL 优先) |
| 数据通信 | 内置 MQTT/WS/HTTP/SSE/SQL + 数据点绑定 | 无,需自接 | 无,需自接 | 无,需自接 |
| 条件告警 / 生命周期 | 内置 | 无 | 无 | 无 |
| 在线多人协作 | 2.0 内置差量同步 | 需自建 | 需自建 | 需自建 |
| 编辑器交互 | 内置(吸附 / 层级 /undo/redo/Web 组件) | 部分,需自行组装 | 部分(选择 / 变换) | 无 |
| 典型场景 | 组态、SCADA、监控大屏、流程图 | 画板、标注、H5 交互 | 图片 / 海报编辑器 | 游戏、高性能可视化 |
| 开源协议 | MIT | MIT | MIT | MIT |
怎么选型:
-
想要高性能渲染 → Meta2d.js / PixiJS;
-
想要通用绘图交互 → Meta2d.js / Konva / Fabric;
-
想要工业可视化业务开箱即用(组态、SCADA、大屏、流程图 + 实时数据 + 协作)→ Meta2d.js。
一句话:不用自己接 MQTT/WebSocket、不用自己写拾取和局部渲染优化、不用自己搭编辑器交互、不用自己实现多人协作 —— 选 Meta2d.js 2.0
五、Meta2d.js 2.0 关键设计
5.1 多线程架构
2.0 把整个引擎拆成 1 个主线程 + 4 个 Web Worker(packages/core/src/workers/):
- 渲染线程 持有OffscreenCanvas,绘制指令不再经过主线程。拖拽、缩放、动画播放时主线程保持「零占用」;
- 计算线程 负责拾取、视口裁剪、包围盒与脏区计算 —— 这些是编辑场景里每帧都会发生的重活;
- 交互线程 负责图元动态交互下的状态管理和交互响应;
- 工具线程 承载所有协议连接(MQTT/WebSocket/HTTP/SSE/SQL)和图片 / GIF 解析,握手、心跳、断线重连不影响界面;
5.2 局部重绘
1.x 采用整幅画布 clear + 全量重绘,逻辑简单稳定;2.0 在此基础上进一步升级为按包围盒的局部重绘。2.0 为每个图元维护包围盒(boundary) ,并预先计算其影响范围内的所有图元(penBoundarys),渲染线程只对脏区域执行 clearRect + clip:
// workers/render/worker.ts(关键逻辑)
if (boundary && boundary.width > 0 && pens === patchPens) {
// 计算屏幕像素对齐的脏区
ctx.clearRect(x, y, width, height);
// 设置局部重绘区域
ctx.beginPath();
ctx.rect(x, y, width, height);
ctx.clip();
}
几个典型的增量场景:
- 拖拽移动:先擦除并重绘「老位置」区域,再绘制「新位置」区域,两处脏区之外分毫不动:
// 1. 先擦除并重绘老位置区域
if (e.data.oldBoundary) {
boundary = e.data.oldBoundary;
renderPens(ctx, patchPens, true);
}
// 2. 重绘新位置区域
boundary = e.data.newBoundary;
renderPens(ctx, patchPens, true);
2. 悬停 / 选中:记录上一帧绘制过的图元集合(lastHoverPens / lastInActivePens),状态切换时只清除并重绘这些图元;
- 动画刷新:每一帧动画只重绘动画图元所在包围盒内的图元;
- 文字溢出感知:文字溢出 pen 范围时,textBox 会同步进拾取范围(textOutsides 回传 calc 线程),保证重绘完整覆盖。
5.3 空间网格拾取:从「全部遍历」到「只查一格」
拾取(pick)是编辑器的命门。1.x 采用线性遍历拾取,在万级图元下仍有明显优化空间;2.0 引入自适应空间网格索引(workers/calc/pick.ts),把拾取成本进一步大幅压低:
// 图元少于 2000 个时,整幅画布一个格
if (penMap.size < 2000) {
cols = 1; rows = 1;
cellSize = Math.max(width, height);
} else {
// 动态计算网格行列数
const size = Math.ceil(penMap.size / 1000);
...
}
拾取时先根据鼠标坐标定位到所在 cell,只遍历该格内的候选图元(grid[cell]),候选集合从「全部 N 个」降到「本格 ≤1000 个」。配合几个细节优化:
- 连线外扩 5px:expandRect(pen, 5),避免细线难命中;
- 曲线采样点缓存:linePoints Map 缓存贝塞尔曲线分段采样点,拾取曲线时不用每帧重算;
- 旋转坐标反变换:pick 时把鼠标坐标变换到图元本地坐标系,旋转图元也能精确命中;
- 文字溢出区域参与命中:textBoxs 纳入网格检测,点文字溢出部分也能选中。
5.4 原生解析 GIF / APNG,实现动图自由
工业大屏里 GIF 动图的播放一直受制于浏览器 的能力:无法控制帧率与暂停,频繁解码还会阻塞主线程。2.0 在工具线程里做了帧级原生解析:
- 支持 GIF 与 APNG 两种动图格式,统一输出 { imageBitmap, duration } 帧序列;
-
渲染线程内置 GIF 播放器(gifPlayers),按每帧 duration 推进帧索引,配合局部重绘只刷新动图所在区域:
-
解析结果分批回传(每 50ms 或全部完成时批量 postMessage),ImageBitmap 直接转移所有权,不复制内存。
5.5 动画引擎优化
2.0 的动画播放器(workers/calc/animate.ts)整体搬进 calc 线程:关键帧插值在 Worker 内完成,每帧只把变化属性(changedProperties)发给渲染线程做局部重绘。1000+ 动画同屏播放时,主线程与渲染线程既不干扰,性能也大大幅度提升。
5.6 在线多人协作
这是社区期待已久的能力,也是 2.0 全新设计的patch特性考虑特性之一。设计要点:
- 差量同步:与引擎补丁机制完全同的构协作消息结构,天然支持增量与协作渲染 —— 远端收到 patch 只做一次对应的局部重绘;
- 历史回放:新成员进入房间,服务端回放历史差量,即完成协作统一;
- 房间机制:通过 accessToken 作为房间号,同一房间共享同一份协作数据;
- 可编程事件:协作数据通过 collaborate 事件对外广播,业务层可自行处理光标、通知、权限等扩展;
六、(几行代码)快速上手
npm install @meta2d/core @meta2d/<extension> --save
<le5le-meta2d />
import { createMeta2d, Mode } from '@meta2d/core';
createMeta2d();
const meta2d = document.querySelector('le5le-meta2d');
// 加载数据
fetch('data.json').then((res) => res.json()).then((data) => meta2d.open(data));
// 设置编辑模式。默认为运行模式
meta2d.setMode(Mode.Edit);
结语
本着给用户带来更友好的体验,Meta2d.js 2.0 不惜全新重构,把「渲染、拾取、通信」重写架构设计,用空间索引 + 局部重绘把每一帧的无效计算压到最低,再用差量 patch 打通多人协作。对于组态、SCADA、大屏这类「图元多、数据实时、要交互编辑」的场景,带来更好体验和能力跃迁。
资源链接:
- GitHub:github.com/le5le-com/m…
- 在线体验:v.le5le.com
- 相关文档:doc.le5le.com