06 · 渲染与可视化方案

3 阅读4分钟

按「图表 / 关系 / 地理 / 3D / 自定义」五条线给推荐组合与边界。

1. 渲染方式选择

方式适用性能备注
SVG元素少 (< 1k)、强交互、可读DOM 重,节点多会卡
Canvas 2D中等数据量 (1k~10k)主流图表库默认
WebGL大数据量 (10k+) / 3D上手成本高
WebGPU未来方向极高浏览器支持仍在演进

ECharts、AntV G2 都默认 Canvas,可切 SVG;超大数据量用 ECharts GL 或换 deck.gl。

2. 通用 2D 图表:ECharts

适合 90% 大屏场景。

2.1 在 React/Vue 里的轻量封装

function EChart({ option, theme = 'dark-blue', style }: Props) {
  const ref = useRef<HTMLDivElement>(null);
  const inst = useRef<echarts.ECharts>();
  useEffect(() => {
    inst.current = echarts.init(ref.current!, theme);
    const obs = new ResizeObserver(() => inst.current?.resize());
    obs.observe(ref.current!);
    return () => { obs.disconnect(); inst.current?.dispose(); };
  }, [theme]);
  useEffect(() => { inst.current?.setOption(option, { notMerge: false, lazyUpdate: true }); }, [option]);
  return <div ref={ref} style={{ width: '100%', height: '100%', ...style }} />;
}

要点:

  • ResizeObserver 而不是 window.resize,因为大屏组件常在 transform scale 容器里。
  • lazyUpdate: true + notMerge: false:累计更新,性能更好。
  • 大屏不要频繁 dispose / init;切换数据用 setOption。

2.2 ECharts 大数据优化

  • 折线 > 1 万点:开 large: true, largeThreshold: 2000, sampling: 'lttb'
  • 散点 > 5 万:用 echarts-gl 的 scatter3D 或换 deck.gl ScatterplotLayer。
  • 频繁更新:避免 notMerge: true;用 appendData 流式追加。

3. 强语法图表:AntV G2 / G2Plot

const chart = new Chart({ container: 'c1', autoFit: true, theme: 'dark' });
chart
  .interval()
  .data(data)
  .encode('x', 'month').encode('y', 'sales').encode('color', 'city')
  .scale('color', { range: theme.series });
chart.render();

更适合「统计学」场景:分面、统计变换、复杂坐标系。日常直方图、柱线图,ECharts 写起来更快。

4. 关系 / 流程 / 知识图谱:AntV G6

  • 节点 1k 以内:直接用,交互流畅。
  • 1k~10k:开启 enableStack: false,用 webworker 布局。
  • 10k+:考虑 GPU 渲染或换 Cytoscape.js + Sigma.js。
const graph = new G6.Graph({
  container: 'g6',
  layout: { type: 'force', preventOverlap: true },
  defaultNode: { size: 30, style: { fill: theme.primary } },
  defaultEdge: { style: { stroke: theme.textDim } },
});
graph.data(graphData);
graph.render();

5. 地理可视化

5.1 选型矩阵

场景推荐
中国合规、政企高德 / 百度 JS API + AntV L7 叠图层
全球地图、商业可控Mapbox GL JS + deck.gl
离线 / 私有部署MapLibre GL + 自建 vector tile (TileServer GL)
真实地球 / 时空回放Cesium(含影像、地形、3D Tiles)
简单点图 / 老项目Leaflet

5.2 deck.gl 大数据图层

deck.gl 是 Uber 的 WebGL 图层库,与 Mapbox 无缝结合,能画百万级散点/弧线/热力。

const map = new mapboxgl.Map({ container: 'map', style: 'mapbox://styles/...' });
const overlay = new MapboxOverlay({
  layers: [
    new ScatterplotLayer({ id: 'pts', data, getPosition: d => d.coord, radiusMinPixels: 2 }),
    new ArcLayer({ id: 'arcs', data: arcs, getSourcePosition: d => d.from, getTargetPosition: d => d.to }),
  ],
});
map.addControl(overlay);

5.3 AntV L7

国内首选地理可视化层,与高德/Mapbox 都能配,飞线、热力、3D 柱、轨迹做得最齐:

const scene = new Scene({ id: 'l7', map: new GaodeMap({ token: '...' }) });
scene.on('loaded', () => {
  scene.addLayer(new HeatmapLayer().source(data).shape('heatmap').size('count', [0, 1]));
});

6. 3D / 数字孪生

6.1 Three.js 经典栈

const scene    = new THREE.Scene();
const camera   = new THREE.PerspectiveCamera(45, w / h, 0.1, 5000);
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setPixelRatio(1);     // 大屏锁 dpr
renderer.setSize(w, h);
container.appendChild(renderer.domElement);

const ctrls = new OrbitControls(camera, renderer.domElement);

(function loop() {
  ctrls.update();
  renderer.render(scene, camera);
  requestAnimationFrame(loop);
})();

要点:

  • 共用 renderer:一屏多 3D 视口用一个 WebGLRenderer + scissor,性能最优。
  • InstancedMesh 渲染同模型大量副本(如车队、楼栋)。
  • GLTF + Draco:模型必须压缩,单个 > 5MB 在大屏长时间运行会内存涨。
  • 后处理(Bloom/FXAA)按需开;监控大屏一律关。

6.2 数字孪生组合

Cesium 或 Mapbox (底图地形)
  ↑ 叠加
deck.gl / L7 (大数据图层)
  ↑ 叠加
Three.js 自定义模型(独立 canvas 同步相机,或用 Threebox/cesium-three 桥)

桥接库:

  • Threebox:Mapbox + Three.js 摄像机同步。
  • cesium-three / 自写 sync:Cesium 与 Three.js 联动需手动同步矩阵。

6.3 性能红线

  • 三角面:< 200 万总场景;高于这个数低端机器开始掉帧。
  • 纹理:合并图集;单纹理 ≤ 2048×2048。
  • 阴影:实时阴影 only for 关键模型;其他用 baked shadow 或 fake AO。

7. 自定义画法(D3 / Canvas / Pixi.js)

  • D3:教育、研究、特殊形态(弦图、Sankey 进阶)。日常大屏不要默认上 D3。
  • 原生 Canvas 2D:写自定义 KPI 数字滚动、波形、雷达扫描,简单稳定。
  • Pixi.js:2D WebGL 框架,做粒子、飞线、电子城市平面图非常合适,比 Three.js 上手快。

8. 视频背景与混合渲染

  • 大屏底层用 <video autoplay loop muted> 做沉浸背景,覆盖一层半透明面板放图表。
  • 注意:浏览器自动播放策略——必须 muted 才能 autoplay;Chromium-based 浏览器在 Kiosk 模式下放宽。
  • 视频预加载:把 mp4/webm 放本地,避免 CDN 抖动;Electron 直接打包资源。

9. 帧率与渲染节流

  • 多个 Canvas 各自 RAF 会重叠:建一个全局调度器,用一个 RAF 循环触发所有需要重绘的图层,避免 60+ 个 RAF 同时跑。
  • 不可见组件停止渲染:IntersectionObserver + 可视化库的 pause API。

10. 反模式

  • 同屏混用 ECharts + AntV G2 + Chart.js:包大、风格漂;选一个为主。
  • 把所有图表都画到同一块 WebGL canvas:调试地狱。HTML 浮层 + 各自 canvas 才是大屏正确姿势。
  • 用 SVG 画上万点:DOM 直接卡死。
  • Three.js 没有 dispose:切大屏时纹理与几何泄漏,运行 1 小时显存涨爆。