SVG 和 Canvas 是两种主流的 Web 图形技术,各有优缺点和适用场景。以下是详细对比:
1. 基础概念
| 特性 | SVG (Scalable Vector Graphics) | Canvas |
|---|---|---|
| 类型 | 矢量图形(基于 XML 描述图形) | 位图(通过 JavaScript 动态绘制像素) |
| 渲染方式 | 由浏览器解析 XML 并渲染(DOM 的一部分) | 通过 JavaScript API 直接操作像素 |
| 分辨率 | 无限缩放,不失真(矢量特性) | 依赖画布尺寸,放大后可能模糊 |
| 交互支持 | 原生支持事件绑定(如 click、mouseover) |
需手动计算坐标实现交互 |
| 适用场景 | 图标、地图、可交互图表、动态 UI 元素 | 游戏、数据可视化、图像处理、动画 |
2. 技术细节对比
2.1 语法与结构
SVG:
1
2
3<svg width="200" height="200">
<circle cx="100" cy="100" r="50" fill="red" onclick="alert('clicked!')" />
</svg>- 通过 XML 标签定义图形,支持 CSS 和 JavaScript 操作。
Canvas:
1
<canvas id="myCanvas" width="200" height="200"></canvas>
1
2
3
4
5const ctx = document.getElementById('myCanvas').getContext('2d');
ctx.fillStyle = 'red';
ctx.beginPath();
ctx.arc(100, 100, 50, 0, Math.PI * 2);
ctx.fill();- 完全依赖 JavaScript API 绘制,无内置图形对象。
2.2 性能
| 场景 | SVG | Canvas |
|---|---|---|
| 静态图形 | 较高(浏览器优化渲染) | 极高(直接操作像素) |
| 动态更新 | 较差(频繁 DOM 操作成本高) | 极佳(适合高频重绘,如游戏) |
| 图形复杂度 | 适合简单或中等复杂度图形 | 适合高复杂度或大量图形(如粒子效果) |
2.3 功能对比
| 功能 | SVG | Canvas |
|---|---|---|
| 文本渲染 | 完美支持(可选中、SEO 友好) | 需手动绘制,不支持文本选择 |
| 动画 | 通过 CSS/JS 或 SMIL 实现 | 需手动控制每一帧(如 requestAnimationFrame) |
| 图像处理 | 仅支持基础滤镜(如模糊、阴影) | 支持像素级操作(如 getImageData) |
| 响应式适配 | 自动缩放(矢量特性) | 需监听窗口事件并重绘 |
3. 选择建议
优先使用 SVG 的场景
- 需要 矢量缩放(如图标、Logo)。
- 需要 交互事件(如可点击的地图区域)。
- 图形复杂度较低且需与 DOM 协同(如动态图表)。
优先使用 Canvas 的场景
- 高频更新(如游戏、实时数据可视化)。
- 大量图形渲染(如粒子系统、复杂动画)。
- 需要像素级操作(如图像编辑器、滤镜效果)。
4. 代码示例对比
示例1:绘制一个可交互的圆形
SVG(直接绑定事件):
1
2
3
4<svg width="200" height="200">
<circle cx="100" cy="100" r="50" fill="blue"
onclick="this.setAttribute('fill', 'red')" />
</svg>Canvas(需手动计算点击区域):
1
2
3
4
5
6
7
8
9
10
11
12
13
14const canvas = document.getElementById('myCanvas');
canvas.addEventListener('click', (e) => {
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left, y = e.clientY - rect.top;
const ctx = canvas.getContext('2d');
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'blue';
ctx.beginPath();
ctx.arc(100, 100, 50, 0, Math.PI * 2);
if (ctx.isPointInPath(x, y)) {
ctx.fillStyle = 'red';
}
ctx.fill();
});
5. 结合使用
实际项目中可混合使用两者:
- Canvas 为主:处理高性能渲染(如游戏背景)。
- SVG 覆盖:添加可交互的 UI 元素(如按钮、提示框)。
总结
| 维度 | SVG | Canvas |
|---|---|---|
| 图形类型 | 矢量 | 位图 |
| 交互性 | 原生支持 | 需手动实现 |
| 性能 | 适合静态或低频更新 | 适合高频动态渲染 |
| 复杂度 | 适合中小规模图形 | 适合大规模或像素级操作 |
| 学习曲线 | 简单(类似 HTML) | 较高(需掌握绘图 API) |
根据需求选择技术,或结合两者优势实现复杂应用!