canvas适合像素级高频重绘(如游戏、实时波形),svg适合需dom交互、响应式与无障碍的矢量图形(如图标、图表);二者常混合使用,各取所长。

canvas 和 SVG 不是“选一个就对了”的关系,关键看你要画什么、怎么交互、是否需要响应式或无障碍支持。
Canvas 适合:像素级控制、高频重绘、游戏或数据可视化中的大量动态点
Canvas 是位图,getContext('2d') 返回的是绘图上下文,所有操作都作用于像素缓冲区。它不保留绘制对象的结构信息,画完就“忘了”。
- 适合每秒重绘几十次的场景(比如粒子系统、实时波形图)
- 导出为
toDataURL()或toBlob()直接得图片,适合截图、上传 - 无法用 css 选中或样式化单个图形,事件只能靠坐标计算(比如用
isPointInPath()判断点击位置) - 缩放时会模糊,除非手动监听
window.devicePixelRatio并重设canvas.width/height
const canvas = document.getElementById('myCanvas'); const ctx = canvas.getContext('2d'); ctx.fillStyle = 'red'; ctx.beginPath(); ctx.arc(100, 100, 20, 0, Math.PI * 2); ctx.fill(); // 这个圆一旦画完,就只是像素,没有“圆对象”概念
SVG 适合:图标、图表、可缩放矢量图、需 DOM 交互或 seo/无障碍的图形
SVG 是 xml 标签构成的 DOM 树,每个 、 都是真实节点,能绑定事件、加 class、用 CSS 动画、被屏幕阅读器读取。
- 天然响应式:
viewBox属性让 SVG 自适应容器宽高,不糊 - 可直接用
document.querySelector('circle')拿到元素,改cx、fill等属性即可更新 - 适合静态或低频更新的图形(比如地图标注、流程图),但上万节点时性能会明显下降
- 不能直接用
drawImage()绘制,想混合 Canvas 内容得转成或用canvg库
混合使用很常见:SVG 做骨架 + Canvas 渲染动态层
比如一个股票 K 线图:SVG 画坐标轴、文字标签、网格线(稳定、可缩放、可选中);Canvas 叠在上面画实时价格折线(高频更新、抗锯齿好、GPU 加速)。
立即学习“Java免费学习笔记(深入)”;
- 用
position: absolute让两者对齐,注意transform: scale()对 Canvas 的影响比 SVG 复杂 - 鼠标事件需统一坐标系:SVG 用
getScreenCTM()转换,Canvas 用getBoundingClientRect()手动算偏移 - 导出整图时,得分别处理 SVG 的
outerhtml和 Canvas 的toDataURL(),再合成
真正容易被忽略的是文本渲染和字体 fallback:Canvas 里 fillText() 不支持自动换行、富文本或本地字体加载失败静默降级;SVG 的 支持 textLength、lengthAdjust,还能用 @font-face。如果图形里有大量中文或需要打印,SVG 的文本可靠性高得多。