全面对比SVG和Canvas的特点、优缺点和适用场景。帮助开发者选择合适的前端图形技术方案。 前端绑图主要有两种技术:SVG 和 Canvas。它们各有特点,选对了事半功倍,选错了可能要重构。
一句话概括:SVG 是声明式的,Canvas 是命令式的。
| 特性 | SVG | Canvas |
|---|---|---|
| 渲染方式 | 矢量(保留模式) | 位图(立即模式) |
| 图形操作 | DOM 元素 | 像素操作 |
| 事件处理 | 原生支持 | 手动计算 |
| 缩放效果 | 无损 | 有损(模糊) |
| 性能 | 节点多时差 | 节点多时好 |
| 文件格式 | 文本 XML | 二进制/图片 |
SVG 创建的每个图形都是 DOM 元素,浏览器会记住它们。你可以随时修改属性、添加事件。
点击图形改变颜色(SVG 原生事件)
<svg>
<rect id="myRect" fill="#3498db" onclick="changeColor()"/>
</svg>
<script>
document.getElementById('myRect').setAttribute('fill', 'red');
</script>
Canvas 是一块画布,画上去就变成像素了。想修改?重画一遍。
Canvas 画完后无法直接操作单个图形
const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
ctx.fillStyle = '#3498db';
ctx.fillRect(10, 10, 80, 80);
ctx.fillStyle = '#2ecc71';
ctx.beginPath();
ctx.arc(150, 50, 40, 0, Math.PI * 2);
ctx.fill();
// 想修改?只能重画
ctx.clearRect(0, 0, 200, 100);
ctx.fillStyle = 'red';
ctx.fillRect(10, 10, 80, 80);
100 个元素:流畅
500 个元素:开始卡顿
SVG:每个图形都能绑定事件,像普通 DOM 元素一样。
<svg>
<rect onclick="handleClick()" onmouseover="handleHover()"/>
</svg>
Canvas:没有原生事件支持,需要自己计算点击位置。
canvas.addEventListener('click', (e) => {
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
// 手动判断点击了哪个图形
if (x > 10 && x < 90 && y > 10 && y < 90) {
handleClick();
}
});
SVG:三种方式可选
Canvas:只能用 JavaScript,需要手动实现动画循环。
function animate() {
ctx.clearRect(0, 0, width, height);
// 重绘所有内容
requestAnimationFrame(animate);
}
animate();
SVG:文本是可选中的,支持搜索。
Canvas:文本画上去就是像素,无法选中。
SVG:内置丰富的滤镜,如模糊、投影、颜色矩阵等。
Canvas:部分滤镜支持,复杂效果需要手动实现。
很多项目会同时用到两者。比如:
画一个带描边的圆形:
SVG 方式
<svg width="100" height="100">
<circle cx="50" cy="50" r="40"
fill="#3498db"
stroke="#2c3e50"
stroke-width="3"/>
</svg>
Canvas 方式
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.arc(50, 50, 40, 0, Math.PI * 2);
ctx.fillStyle = '#3498db';
ctx.fill();
ctx.strokeStyle = '#2c3e50';
ctx.lineWidth = 3;
ctx.stroke();
SVG 更简洁直观,Canvas 更灵活可控。