Meta2d.js 2.0 Rewrites the 2D Visualization Engine for Million-Node Canvases and Built-In Collaboration
Preface
Meta2d.js is a domestic open-source 2D visualization engine used to quickly build Web HMI/SCADA, monitoring dashboards, flowcharts, central-control visualizations, and graphic editing/interaction applications — it connects to real-time data, sets animations and conditions, and the view updates automatically in real time. It also supports drawing, editing, and interaction. Meta2d.js serves a large number of industrial and IoT projects with its "data-driven display" philosophy, and the performance of 1.0 was already solid. Now, after a year of self-revolution, it has been completely restructured and rewritten — the rendering pipeline, event picking, animation system, and data communication have all been rebuilt from scratch, aiming for even higher performance and adding multiplayer collaboration from zero.
1. What is Meta2d.js
Meta2d.js is an open-source 2D visualization engine, whose core is "data-driven display + dynamic interaction":
- Data changes drive real-time view updates
- Immediate response to conditions, interactions, messages, and events
Typical use cases
Industrial HMI / SCADA: power, water, energy, factory line monitoring, with device points, pipelines, and alarm linkage;
Monitoring dashboards / central-control visualization: smart buildings, data-center environment monitoring, transportation dispatch, with animated graphics and real-time data on the same screen;
Flowchart / architecture-diagram editors: topology, ER, and org charts, with built-in editing interaction out of the box;
Reports / data visualization: real-time data-driven dashboard reports;
Visualization product base: MIT-licensed, use it to build your own designer/editor.
2. A visualization base for the AI era
Meta2d.js 2.0 does not embed an AI model, but it is naturally AI-friendly:
Data-driven, output renders directly
The core of the engine is "data + algorithm + style = lifelike", essentially a structured JSON. After AI generates visualization data, the engine displays it immediately — achieving "AI generates → visualize" instant presentation.
Supports generative, progressive experiences
It easily supports AI-generated, progressive data visualization display.
Solid performance, supports massive nodes
AI can generate 100,000 or 1,000,000+ nodes at once, and they display instantly and run smoothly.
Human-machine same-screen collaboration, auditable changes
Multiplayer collaboration is not limited to humans — AI agents can also act as collaborators to add, delete, and modify the canvas in real time. Delta patches make every AI change syncable, replayable, and auditable; the five-channel real-time data pipeline plus data-point binding lets AI inference results and device data drive the canvas directly.
In a word: AI does the "generation", Meta2d does "rendering, interaction, collaboration" — that is what a visualization base for the AI era should look like.
3. Powerful performance, one million nodes still real-time
Performance benchmark: based on official stress and performance test (examples/benchmark)
Test environment: 8-core 3.8GHz CPU, 32GB RAM
| Nodes | Performance: FPS | Performance: memory (MB) | Notes |
|---|---|---|---|
| 10k | 117 - 120 | 44 - 50 | drag/zoom unaffected |
| 100k | 114 - 120 | 80 - 110 | mouse picking no frame drop |
| 1M | 109 - 117 | 510 - 840 | mouse picking no frame drop |
Note: 200 images, 2000 data points, 400 animations all the same, no extra settings
100k nodes, page zoomed to fit all nodes, canvas not zoomed
100k nodes, page not zoomed, canvas zoomed
1M nodes, page not zoomed, canvas zoomed
A note on the performance optimization: The original plan was to release 2.0 before the Mid-Autumn Festival on September 25, 2026. Our tests showed about 100k nodes were smooth, enough for real production cases. But we developed based on an "architecture -> design implementation" pattern, with performance optimization originally planned after release. Coincidentally, Claude 5.5 and GPT-6 were released, so we decided to try letting AI do deep performance optimization, though previously our engineers designed the new architecture based on five years of accumulated experience, and we were a bit worried AI would "mess up" our code. We were pleasantly surprised that AI's assessment roughly matched ours, and the code changes for optimization were acceptable to us. So we decided to let AI do deep performance optimization before release, which required a lot of review and testing, delaying the release, but the optimized performance exceeded our expectations.
AI analysis: meta2d each animated node computes its own dirty region → each postMessage → render worker does its own clip+clear+redraw for each; hover worker also does full-screen clear and redraw for each N (number of animated nodes) × 2
meta2d's individual primitives (dirty rectangles, spatial grid, worker threads, style diff) are all correct, but there is no aggregation layer within a frame, so the complexity is O(number of animated nodes) independent redraw pipelines, not O(1). With 20k nodes, even if only 200 are animating, each frame is 400 messages + 400 clip/clear/draw + 400 full-screen overlay redraws.
4. Differences from Konva.js, Fabric.js, PixiJS
All are excellent Canvas tech stacks, but the positioning is completely different: Konva / Fabric / Pixi are "canvas basic capability" providers, while Meta2d is a "business out-of-the-box" visualization engine.
| Dimension | Meta2d.js 2.0 | Konva.js | Fabric.js | PixiJS |
|---|---|---|---|---|
| Positioning | Business-level 2D visualization engine | General Canvas drawing interaction library | Canvas object model library | High-performance 2D rendering engine |
| Core selling point | Data-driven display, out of the box | Drawing and interaction (drag/zoom/events) | Object model and serialization (JSON/SVG interchange) | Rendering performance (WebGL first) |
| Data communication | Built-in MQTT/WS/HTTP/SSE/SQL + data-point binding | None, need to integrate | None, need to integrate | None, need to integrate |
| Conditional alarms / lifecycle | Built-in | None | None | None |
| Online multiplayer collaboration | 2.0 built-in delta sync | Need to build | Need to build | Need to build |
| Editor interaction | Built-in (snapping / layers / undo/redo / Web components) | Partial, need to assemble | Partial (selection / transform) | None |
| Typical scenarios | HMI, SCADA, monitoring dashboards, flowcharts | Drawing boards, annotations, H5 interactions | Image/poster editors | Games, high-performance visualization |
| Open source license | MIT | MIT | MIT | MIT |
How to choose:
High-performance rendering → Meta2d.js / PixiJS;
General drawing interaction → Meta2d.js / Konva / Fabric;
Industrial visualization business out of the box (HMI, SCADA, dashboards, flowcharts + real-time data + collaboration) → Meta2d.js.
In a word: no need to integrate MQTT/WebSocket yourself, no need to write picking and partial rendering optimization yourself, no need to build editor interaction yourself, no need to implement multiplayer collaboration yourself — choose Meta2d.js 2.0.
5. Key design of Meta2d.js 2.0
5.1 Multi-threaded architecture
2.0 splits the whole engine into 1 main thread + 4 Web Workers (packages/core/src/workers/):
- Render thread holds OffscreenCanvas, drawing instructions no longer go through the main thread. During drag, zoom, and animation playback, the main thread stays at "zero occupancy";
- Compute thread handles picking, viewport clipping, bounding boxes, and dirty-region computation — the heavy work that happens every frame in editing scenarios;
- Interaction thread handles state management and interaction responses for dynamic node interaction;
- Tool thread carries all protocol connections (MQTT/WebSocket/HTTP/SSE/SQL) and image/GIF parsing; handshake, heartbeat, and reconnection do not affect the UI;
5.2 Partial repaint
1.x used full-canvas clear + full redraw, simple and stable; 2.0 upgrades to per-bounding-box partial repaint. 2.0 maintains a boundary for each node, and precomputes all nodes within its influence range (penBoundarys). The render thread only executes clearRect + clip on dirty regions:
// workers/render/worker.ts (key logic)
if (boundary && boundary.width > 0 && pens === patchPens) {
// compute screen-pixel-aligned dirty region
ctx.clearRect(x, y, width, height);
// set partial redraw region
ctx.beginPath();
ctx.rect(x, y, width, height);
ctx.clip();
}
Several typical incremental scenarios:
Drag move: first erase and redraw the "old position" region, then draw the "new position" region; nothing outside the two dirty regions changes:
// 1. erase and redraw the old position region if (e.data.oldBoundary) { boundary = e.data.oldBoundary; renderPens(ctx, patchPens, true); } // 2. redraw the new position region boundary = e.data.newBoundary; renderPens(ctx, patchPens, true);
Hover / selection: track the set of nodes drawn in the previous frame (lastHoverPens / lastInActivePens); on state change, only clear and redraw those nodes;
Animation refresh: each frame only redraws nodes within the bounding boxes of animated nodes;
Text overflow awareness: when text overflows a node's bounds, the textBox syncs into the picking range (textOutsides are returned to the calc thread), ensuring complete redraw coverage.
5.3 Spatial-grid picking: from "iterate all" to "check one grid"
Picking is the lifeblood of an editor. 1.x used linear traversal, which still had clear room for optimization at tens of thousands of nodes; 2.0 introduces an adaptive spatial grid index (workers/calc/pick.ts) to greatly reduce picking cost:
// when nodes are fewer than 2000, the whole canvas is one grid
if (penMap.size < 2000) {
cols = 1; rows = 1;
cellSize = Math.max(width, height);
} else {
// dynamically compute grid rows and columns
const size = Math.ceil(penMap.size / 1000);
...
}
During picking, first locate the cell based on mouse coordinates, then only traverse candidate nodes within that cell (grid[cell]), reducing the candidate set from "all N" to "this cell ≤1000". Several detail optimizations:
Line expansion by 5px: expandRect(pen, 5), to avoid thin lines being hard to hit;
Curve sampling point cache: a linePoints Map caches Bezier curve segment sample points, so picking curves doesn't recompute each frame;
Rotation coordinate inverse transform: during picking, transform mouse coordinates into the node's local coordinate system, so rotated nodes can be hit precisely;
Text overflow region participates in picking: textBoxs are included in the grid detection, so clicking text overflow parts also selects the node.
5.4 Native GIF / APNG parsing for free animated images
GIF animation on industrial dashboards has always been limited by the browser's <img> capability: you cannot control frame rate or pause, and frequent decoding blocks the main thread. 2.0 does frame-level native parsing in the tool thread:
Supports GIF and APNG formats, uniformly outputting a frame sequence of { imageBitmap, duration };
The render thread has a built-in GIF player (gifPlayers), advancing frame index based on each frame's duration, combined with partial repaint to only refresh the animated image region;
Parsing results are sent back in batches (every 50ms or when all done), and ImageBitmap ownership is transferred directly, without copying memory.
5.5 Animation engine optimization
2.0 moves the animation player (workers/calc/animate.ts) entirely into the calc thread: keyframe interpolation happens inside the Worker, and only changed properties (changedProperties) are sent to the render thread for partial repaint each frame. With 1000+ animations on screen simultaneously, the main thread and render thread never interfere, and performance improves greatly.
5.6 Online multiplayer collaboration
This is a capability long awaited by the community, and one of the patch features newly designed in 2.0. Key design points:
Delta sync: uses a message structure identical to the engine's patch mechanism, naturally supporting increment and collaborative rendering — remote clients only do one corresponding partial repaint upon receiving a patch;
History replay: when a new member joins a room, the server replays historical deltas to achieve collaboration consistency;
Room mechanism: accessToken acts as the room ID; the same room shares the same collaboration data;
Programmable events: collaboration data is broadcast via collaborate events, so business layers can extend cursor, notification, permission, etc.;
6. (A few lines) Quick start
npm install @meta2d/core @meta2d/<extension> --save
<le5le-meta2d />
import { createMeta2d, Mode } from '@meta2d/core';
createMeta2d();
const meta2d = document.querySelector('le5le-meta2d');
// Load data
fetch('data.json').then((res) => res.json()).then((data) => meta2d.open(data));
// Set edit mode. Default is run mode
meta2d.setMode(Mode.Edit);
Conclusion
Dedicated to providing users with a better experience, Meta2d.js 2.0 has completely restructured its "rendering, picking, and communication" architecture, using spatial indexing and partial repaint to minimize wasted computation per frame, and using delta patches to enable multiplayer collaboration. For scenarios like HMI, SCADA, and dashboards — "many nodes, real-time data, need interactive editing" — it brings better experience and a leap in capability.
Resource links:
Online demo: http://v.le5le.com
Documentation: https://doc.le5le.com
Top 2 of 3 from juejin.cn, machine-translated. The original thread is authoritative.
Finally, version 2.0 has arrived!
Thanks for your continued attention.
Great article, thanks for sharing.