Canvas适合高频重绘和像素级控制,SVG适合交互复杂、缩放频繁及SEO友好的场景;二者事件绑定、性能优化、导出与可访问性差异显著。

Canvas 是位图绘制,SVG 是矢量 DOM
Canvas 本质是一块“画布”,调用 getContext('2d') 后所有操作都基于像素点——清空、绘图、变换全靠 JavaScript 指令驱动,画完即丢,不保留图形对象。SVG 则是 XML 格式的文档结构,每个 <circle>、<path> 都是真实 DOM 节点,可被 CSS 选中、JS 查询、事件绑定,缩放不失真。
这意味着:需要高频重绘动画(如粒子系统、实时仪表盘)或像素级控制(滤镜、图像处理),Canvas 更合适;而需要交互复杂、缩放频繁、SEO 友好或需 CSS 动画支持的图表、图标、地图标注,SVG 是更自然的选择。
事件绑定方式完全不同
Canvas 上没有内置“点击某个圆形”的概念——你得自己维护图形坐标、监听 canvas 元素的 click 事件,再用 isPointInPath() 或包围盒计算判断是否击中。SVG 中直接给 <rect id="btn"> 绑定 addEventListener('click', ...) 即可,甚至能用 CSS :hover。
- Canvas 事件要手动做坐标转换(尤其有
transform或滚动时) - SVG 事件冒泡、捕获、委托都和普通 DOM 一致,调试直观
- SVG 中
pointer-events: none可快速禁用某元素响应,Canvas 里得改逻辑分支
性能瓶颈不在“画什么”,而在“怎么管理”
Canvas 单帧绘制上万点可能很流畅,但若每帧都 clearRect() + 全量重绘,CPU/GPU 压力会陡增;SVG 渲染大量节点(比如 5000 个 <circle>)时,DOM 树深度和样式计算开销明显,容易卡顿。
- Canvas 优化重点:减少清屏、合并绘制调用、用
requestAnimationFrame控制节奏、必要时用OffscreenCanvas - SVG 优化重点:避免深层嵌套、慎用
filter和mask、大批量更新用documentFragment批量插入、考虑用<use>复用定义 - 混合方案常见:用 SVG 做静态底图 + Canvas 叠加动态层(如地图上实时轨迹)
导出与可访问性差距明显
Canvas 导出 PNG/JPEG 只需 toDataURL(),但无法提取文字语义、不支持屏幕阅读器;SVG 本身是文本,可内联 <title>、<desc>,支持键盘焦点、ARIA 属性,打印/缩放/复制文字都原生可用。
- 如果图表要被搜索引擎收录或供视障用户使用,SVG 是事实标准
- Canvas 若需导出高清图,要注意设备像素比(
window.devicePixelRatio),否则在 Retina 屏上模糊 - 服务端渲染 Canvas 很麻烦(需 Node.js 环境配 headless WebGL),SVG 可直接吐 XML 字符串
选型真正卡住人的地方,往往不是“哪个更快”,而是“谁更容易让设计师改颜色、让后端吐数据、让测试点到具体元素”。这些隐性成本,比 API 多写两行代码影响大得多。

















