Canvas 与 SVG
这个 topic 真正要回答的不是“哪个更好”
Canvas 和 SVG 很容易被讲成一道二选一题。
例如:
- 性能用 Canvas
- 交互用 SVG
这种总结有一点帮助。
但它不够。
更成熟的理解应该是:
Canvas 和 SVG 代表了浏览器里两种完全不同的图形思维。
Canvas 更像一块像素画布,你负责把结果画上去。
SVG 更像一组图形元素,你把图形对象声明出来,让浏览器去管理它们。
这两种思维的差异,会影响:
- 性能
- 交互
- 调试
- 可访问性
- 维护方式
所以这不是单纯的 API 对比。
它本质上是两套渲染模型的对比。
为什么前端工程师需要真正理解它们
只要你开始做:
- 可视化
- 交互图形
- 编辑器
- 游戏和动画
- 复杂图表
Canvas 和 SVG 的选择就会直接影响工程结果。
这类选择如果只靠经验口诀,常常会在项目变复杂后失效。
所以真正要学的,不是“记结论”。
而是理解两者各自的世界观。
一个更准确的定义
Canvas
Canvas 更适合被理解成:
浏览器中的即时模式绘图表面。
你每次绘制,都是在直接修改最终像素结果。
浏览器并不会自动帮你保留“这个圆”“那个矩形”作为对象语义。
SVG
SVG 更适合被理解成:
浏览器中的声明式矢量图形文档。
你定义的是对象:
- 圆
- 线
- 文本
- 路径
这些对象仍然存在于 DOM 世界里。
“即时模式”和“保留模式”为什么特别值得记
这是理解 Canvas 和 SVG 的关键一句话。
Canvas 更像即时模式。
意思是:
你告诉浏览器现在画什么,画完结果留下,但对象语义不自动保留。
SVG 更像保留模式。
意思是:
你声明对象,浏览器保留对象结构,之后还能继续样式、事件和语义化处理。
只要抓住这点,很多差异就很自然了。
Canvas 为什么经常更适合高密度绘制
Canvas 的优势,不是“它更高级”。
而是它把很多对象管理成本从浏览器那里拿掉了。
对于:
- 很多粒子
- 大量点
- 高频重绘
这种场景,少一层 DOM 对象管理,通常会明显更合适。
所以 Canvas 常常在:
- 游戏
- 高频动画
- 大量数据点可视化
这些场景里更自然。
但 Canvas 为什么又更容易变得难维护
正因为它更接近“把像素画上去”,所以很多事情也得你自己管。
例如:
- 命中检测
- 图元状态
- 分层管理
- 撤销重绘
- 无障碍 fallback
这意味着,Canvas 虽然在渲染层可能更高效,但在工程层不一定更省事。
如果团队没有为“对象管理自行负责”做好准备,就会很快把 Canvas 代码写成难维护的大画布脚本。
SVG 为什么对前端工程师天然更亲切
因为它仍然在 DOM 语境里。
你天然会得到:
- 元素结构
- CSS 样式
- 事件绑定
- DevTools 可见性
- 更好的无障碍基础
这让 SVG 很适合:
- 图标
- 可交互图表
- 流程图
- 少量矢量元素组成的界面
所以 SVG 的强项不是“所有图都能缩放”这么简单。
它的真正价值是:
图形对象仍然保留在前端开发者熟悉的声明式结构里。
为什么“SVG 交互更容易”不只是因为事件
很多人会说 SVG 好做交互,是因为它能直接绑 click 事件。
这当然对。
但更深层的原因是:
SVG 图形对象仍然有独立身份。
这意味着:
- 样式好改
- 状态好挂
- 焦点可管理
- 语义可增强
这对图表和编辑器类场景非常重要。
因为真正难的不是画出图形。
而是让图形可被操作、可被理解、可被调试。
为什么很多可视化项目最后会走向“SVG + Canvas 混合”
这是一个很常见的成熟结果。
因为两者各有强项。
例如:
- 大量背景点和密集层用 Canvas
- 交互层、坐标轴、标签用 SVG
这种分层思路很值得前端工程师记住。
它说明现实工程里最好的答案,常常不是单选题。
而是把不同渲染模型用在最适合的层上。
OffscreenCanvas 为什么重要
OffscreenCanvas 的意义,不在于“又多一个优化 API”。
它真正重要的地方是:
Canvas 终于能更自然地和 Worker 协同,减轻主线程压力。
这对于:
- 高频渲染
- 图像处理
- 编辑器预览
- 复杂动画
都很有意义。
因为只要图形工作过重,前端真正受伤的往往不是 FPS 本身。
而是主线程交互跟着一起变卡。
为什么 hit testing 是 Canvas 工程里的分水岭
很多人做 Canvas,前半段都挺顺利。
直到产品提了这些需求:
- 点某个点要高亮
- 拖某个图元要跟手
- 鼠标移上去要有 tooltip
这时 hit testing 的复杂度就会开始爆发。
因为 Canvas 没有天然保留对象语义。
你要自己知道:
- 当前点到的是谁
- 这个区域对应哪个对象
- 怎样维护空间索引
所以 Canvas 在交互复杂时,并不自动更轻松。
为什么 SVG 在节点很多时会掉得很难看
SVG 之所以舒服,是因为对象还在。
但这也是它的代价。
节点一多,浏览器就要维护:
- DOM
- 样式
- 布局和绘制
- 事件命中
所以 SVG 很容易在“元素数量暴涨”时出现明显性能问题。
这也是为什么很多经验结论会说:
少量高交互对象用 SVG,大量密集对象更偏向 Canvas。
无障碍为什么会把 Canvas 和 SVG 再次拉开
SVG 天生更容易进入无障碍体系。
因为它有元素语义基础,比较容易补标签、title、desc 和焦点行为。
Canvas 则更像一张图片表面。
如果业务真的要让图形本身可达、可读、可聚焦,Canvas 往往需要额外设计辅助结构。
这使得:
在强调可访问性和语义化的项目里,SVG 会天然更占优。
中国互联网语境里为什么 Canvas 常常和大屏、图形编辑、复杂可视化绑在一起
中国互联网里,Canvas 很多时候会在这些场景出现:
- 大屏可视化
- 海量点位图
- 拖拽编辑器
- 低代码设计器
- 营销互动页和游戏化动画
这些场景共同特点是:
- 元素多
- 渲染频繁
- 交互强
所以 Canvas 在中国语境里常常不只是“图形 API”,而是复杂视觉产品的基础设施之一。
海外语境里为什么 SVG 常常更容易和设计工具、图表系统一起出现
海外语境里,设计系统、文档站、分析型图表和交互式可视化产品很多。
这些产品往往更重视:
- 语义结构
- 可维护性
- 可访问性
- 和 DOM/CSS 生态的连续性
这会让 SVG 在很多“中等复杂度但交互丰富”的图形场景里非常顺手。
容易被讲浅的误区
误区一:Canvas 快,所以都该用 Canvas
不对。
快的是某类渲染模式,不代表整体工程更省。
误区二:SVG 适合简单图形,复杂一点就不行
也不对。
很多复杂交互图形系统依然非常适合 SVG,只是节点规模要受控。
误区三:只看初始渲染,不看交互和维护
这是最常见的选型失真。
误区四:二者只能二选一
很多成熟系统其实会混用。
面试或技术分享里怎么讲更成熟
一个更成熟的表达可以是:
Canvas 和 SVG 的差异,核心不在 API 多少,而在渲染模型。Canvas 更像即时模式绘图表面,适合高密度、高频重绘场景,但对象管理和交互命中往往要自己承担;SVG 更像保留模式的矢量文档,天然更适合声明式结构、DOM 交互和无障碍,但在节点规模很大时性能会下降。
真正成熟的选型不是记口诀,而是看对象数量、交互复杂度、可访问性要求和后续维护方式。
实践建议
实践一:同一个小图表分别用 Canvas 和 SVG 实现
不要只比“能不能画出来”。
要比:
- 交互写法
- 调试体验
- 代码结构
实践二:做一个带 hover 命中的 Canvas 例子
这会让你非常快地理解 Canvas 的真实复杂度。
实践三:做一个 SVG 节点数量逐步增加的实验
观察何时开始卡顿,你会对“SVG 为什么不是无限扩展”有更直观的理解。