SVG、Canvas、WebGL:三层渲染技术怎么选

前两篇聊了出图的历史和工具选型,这次落到技术底层:SVG、Canvas、WebGL 这三层渲染技术到底怎么选?

很多人有个误解:SVG 最慢,Canvas 中等,WebGL 最快。就像交通工具的等级递进——自行车、汽车、飞机。但这种直觉是错的。

三种渲染模式的本质差异

先说结论:三种技术的核心区别不是性能,而是渲染模式。

SVG 是保留模式。浏览器维护一棵图形 DOM 树,每个圆、每个矩形都是真实的 DOM 节点。这意味着浏览器要负责解析、布局、重绘,每一步都有开销。但换来的是什么?每个元素天然支持点击、悬停等事件,CSS 样式可以直接改,甚至可以右键查看源码学习。这就是 SVG 在博客图表中无可替代的优势。

Canvas 是即时模式。你发一条 fillRect 指令,画布立刻把这个矩形画成像素,然后什么都不保留了。浏览器不知道这里有个矩形,它只知道这里有一堆像素。这种模式换来了极致的绘制性能,但代价是失去了元素级的操作能力。想点击某个矩形?得自己写命中测试算法,通过坐标判断用户点到了哪里。

WebGL 更彻底的即时模式。它不是 CPU 在画,而是通过 GLSL 着色器语言直接指挥 GPU 工作。顶点着色器计算每个点的位置,片元着色器决定每个像素的颜色。几十万个粒子同时运动,WebGL 毫无压力。但开发成本也跟着涨,你需要懂图形学基础,手写着色器代码。

mermaid
flowchart TD
    A[更新模式] --> B{是否高频重绘}
    B -->|是| C{数据量级}
    B -->|否| D[SVG 交互优先]
    C -->|>5万| E[WebGL]
    C -->|≤5万| F[Canvas 2D]

    style A fill:#FF9800,color:#fff
    style B fill:#2196F3,color:#fff
    style D fill:#4CAF50,color:#fff
    style E fill:#f44336,color:#fff
    style F fill:#2196F3,color:#fff

性能边界的真实测试

数据量确实重要,但不是唯一维度。

SVG 的性能瓶颈在 DOM 节点数。研究显示,几百个节点就开始出现性能下降。一项 2009 年的 Firefox 基准测试表明,渲染 600 个圆形时 Canvas 比 SVG 快约 4 倍。所以社区有个经验值:元素数小于约 2000 时用 SVG,超过就考虑 Canvas。

但这里有个反直觉的发现:在 20,000 个节点的场景下,如果只需要更新单个元素的属性,SVG 比 Canvas 快 7 倍。

为什么?因为 Canvas 的即时模式意味着每次都要重绘整个场景。要改一个圆的颜色,你得清空画布,重新画所有 20,000 个元素。而 SVG 只需要改那个 DOM 节点的样式,浏览器会自动处理局部更新。所以更新的频率和模式,比总元素数更重要。

这个发现打破了"元素越多就越该用更底层技术"的迷信。真实项目的性能瓶颈往往不在绘制,而在重绘成本。如果你的场景是低频更新、高交互需求,即使元素数过万,SVG 仍然是合理选择。

mermaid
flowchart TD
    A[选型决策] --> B{更新模式}
    B -->|全量刷新| C{数据规模}
    B -->|局部更新| D[SVG<br/>保留模式]
    C -->|>5万| E[WebGL]
    C -->|≤5万| F[Canvas 2D]

    style A fill:#FF9800,color:#fff
    style B fill:#2196F3,color:#fff
    style D fill:#4CAF50,color:#fff
    style E fill:#f44336,color:#fff
    style F fill:#2196F3,color:#fff

技术演进的时间线

理解这些技术的历史,有助于判断它们各自的优势领域。

SVG 早在 2001 年就成为了 W3C 推荐标准,比 HTML5 早了近十年。它的设计初衷就是成为网页矢量图形的标准,因此从一开始就强调与 HTML、CSS 的集成。2018 年 SVG 2.0 候选推荐标准发布,核心目标是改善与 CSS、HTML、WOFF 等标准的兼容性。虽然截至当前 SVG 2 仍处于候选推荐阶段,但主流浏览器已广泛实现其核心特性。

Canvas 的诞生很有意思。2004 年,Apple 为了 Safari 及 macOS Dashboard 小部件引入了 Canvas 元素作为 WebKit 专有扩展。2005 年 Apple 将规范提交给 WHATWG,才让它成为 HTML5 的一部分。Canvas 现归属 HTML Living Standard,2015 年起在主流浏览器中基线广泛可用。

WebGL 的故事从 2006 年开始。工程师 Vladimir Vukićević 在 Canvas 标签上做了原型项目 Canvas3D,用 Canvas 实现 OpenGL。这个项目被 Mozilla 等浏览器厂商看中并继续推进,最终演化为 WebGL。2011 年 WebGL 1.0 标准正式发布,由 Khronos Group 主导,基于 OpenGL ES 2.0。它标志着网页端 3D 图形渲染首次无需插件。

2017 年 WebGL 2.0 标准发布,底层基于 OpenGL ES 3.0。但值得注意的是,苹果在 2014 年推出 Metal API 后将 OpenGL 标记为"遗留技术",导致 Safari 直到 2021 年 9 月才支持 WebGL 2.0。当前约 97% 的移动设备已支持 WebGL 2.0。

WebGPU 是最新的提案,但它不是 WebGL 的继承,而是全新提案,更像"浏览器中的 Vulkan"。截至 2024 年 11 月仍为 W3C 工作草案。Chrome 113 首次正式提供 WebGPU,Firefox 141 和 Safari 26 也已支持。

mermaid
flowchart TD
    A[技术演进] --> B[SVG<br/>2001 W3C 标准]
    A --> C[Canvas<br/>2004 Apple 引入]
    A --> D[WebGL<br/>2011 GPU 加速]
    A --> E[WebGPU<br/>2023 计算着色器]

    style A fill:#FF9800,color:#fff
    style B fill:#4CAF50,color:#fff
    style C fill:#2196F3,color:#fff
    style D fill:#9C27B0,color:#fff
    style E fill:#f44336,color:#fff

适用场景不是"先进性"决定的

WebGPU 很新,支持计算着色器,可以跑 AI 推理,听起来很厉害。但如果不做 3D 场景、不需要物理模拟,那 WebGPU 对你来说就是屠龙之技。工程上更现实的建议是:渐进增强,先把瓶颈模块迁移到 WebGL,稳定后再考虑 WebGPU。而且要做完整的回退链路:WebGPU 失败就降级到 WebGL,再失败就回 Canvas。

真正影响选型的,是三个维度:吞吐量需求、维护成本、兼容成本。

运营报表、流程图、节点数小于 2000 的可视化?用 SVG。语义化强,DOM 可编辑性好,右键还能查看源码学习。博客图表的最佳默认选择。

中等规模 2D 实时图(2K-20K 图元),比如仪表盘、组态大屏、2D 设备监控?用 Canvas 2D。工程成本低,性能更稳。记得用脏矩形更新避免全量重绘,高频数据用 requestAnimationFrame 加批处理节流。

大规模粒子系统、拓扑动画、热力图、点云渲染?用 WebGL。生态成熟,跨端稳定。Babylon.js、deck.gl 等库已经把复杂性封装好了。

复杂 3D 场景、需要并行计算(含 AI 推理)?用 WebGPU。但要做好兼容测试,毕竟 Safari 2021 年 9 月才支持 WebGL 2.0,WebGPU 的落地还在推进中。

mermaid
flowchart TD
    A[交互需求] --> B{需要原生事件}
    B -->|是| C[SVG]
    B -->|否| D{维度}
    D -->|2D 2K-20K| E[Canvas 2D]
    D -->|2D >20K| F[WebGL]
    D -->|3D| F

WebGPU 的真正价值

很多人把 WebGPU 当成 WebGL 3.0,这是误解。WebGPU 不是 WebGL 的继承,而是全新提案。

WebGPU 的核心优势在于暴露现代 GPU 特性。它支持多线程指令提交(Command Buffer)、显式资源管理,可以最大化 GPU 利用率。更重要的是支持计算着色器(Compute Shader),可以直接运行通用计算(物理模拟、AI 推理),而 WebGL 仅限图形渲染。

性能实测很惊人。对 Babylon.js 的 WebGL 与 WebGPU 同场景对比,WebGPU 帧数提升约 50 帧,CPU 耗时从 63ms 降至 0.2ms。但这不意味着所有项目都应该用 WebGPU。

WebGPU 的真正价值场景:复杂 3D 场景、并行计算需求(含 AI 推理)、神经渲染等新兴场景。如果你的项目是 2D 可视化,WebGPU 带来的收益很难覆盖开发成本。

而且兼容成本不低。Chrome 113 才首次正式提供 WebGPU,Firefox 141、Safari 26 也已支持,但内网环境、旧版浏览器的兼容性仍需考虑。工程建议:短期 WebGPU 不会取代 WebGL,两者长期共存。

mermaid
flowchart TD
    A[WebGPU 评估] --> B[需要 3D 或计算?]
    B -->|是| C[WebGPU 主方案]
    B -->|否| D[WebGL/Canvas 更稳]
    C --> E[做兼容降级<br/>WebGPU→WebGL→Canvas]

    style A fill:#FF9800,color:#fff
    style B fill:#2196F3,color:#fff
    style C fill:#9C27B0,color:#fff
    style D fill:#4CAF50,color:#fff
    style E fill:#f44336,color:#fff

工程建议:不要被"先进性"绑架

很多人在做技术选型时,会被"新技术更先进"的想法绑架。

WebGL 2011 年就发布了,Canvas 2004 年就出现了,SVG 2001 年就是 W3C 推荐标准了。这些技术不是相互取代,而是按数据规模与交互需求分层共存。

核心原则只有一个:用"吞吐量 + 维护成本 + 兼容成本"选技术,不要用"先进性"选技术。

从工程实践的角度,建议把"绘制"与"命中测试"分层。可以用离屏 Canvas 做预渲染,主 Canvas 做显示。脏矩形更新避免全量重绘。高频数据用 requestAnimationFrame 加批处理节流。这些优化往往比盲目升级渲染技术更有效。

还有一个容易被忽视的点:学习曲线。SVG 用 HTML/CSS 风格开发,前端工程师上手很快。Canvas 需要自管渲染循环与命中测试,复杂度中等。WebGL 需要图形学与着色器基础,开发成本高。WebGPU 的学习曲线更陡峭。

团队的技术栈也很重要。如果团队已经熟练使用 D3.js,那 SVG 渲染器就是自然选择。如果团队有图形学背景,WebGL 不再是障碍。选型要考虑团队能力,不要追求技术而忽视了可实现性。

下一篇聊把这些技术组合起来的实际案例,以及在大规模可视化项目中如何做性能调优。