Canvas、SVG、WebGL 对比
三种浏览器图形技术的区别和使用场景
问题
Canvas、SVG、WebGL 有什么区别?分别适合什么场景?
解答
对比表格
| 特性 | Canvas | SVG | WebGL |
|---|---|---|---|
| 渲染方式 | 位图(像素) | 矢量(DOM) | 3D(GPU) |
| 缩放 | 会模糊 | 不失真 | 不失真 |
| 事件绑定 | 需要手动计算 | 直接绑定元素 | 需要手动计算 |
| 性能 | 适合大量像素操作 | 元素多时变慢 | 最高(GPU加速) |
| 学习成本 | 低 | 低 | 高 |
Canvas 示例
<canvas id="canvas" width="200" height="200"></canvas>
<script>
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
// 绘制矩形
ctx.fillStyle = '#3498db';
ctx.fillRect(50, 50, 100, 100);
// 绘制圆形
ctx.beginPath();
ctx.arc(100, 100, 40, 0, Math.PI * 2);
ctx.fillStyle = '#e74c3c';
ctx.fill();
// Canvas 是即时模式,绘制后无法直接操作图形
// 需要清除重绘来实现动画
</script>
SVG 示例
<svg width="200" height="200">
<!-- 矩形 -->
<rect
x="50" y="50"
width="100" height="100"
fill="#3498db"
id="myRect"
/>
<!-- 圆形,可直接绑定事件 -->
<circle
cx="100" cy="100" r="40"
fill="#e74c3c"
onclick="alert('clicked!')"
style="cursor: pointer;"
/>
</svg>
<script>
// SVG 元素是 DOM 节点,可以直接操作
const rect = document.getElementById('myRect');
rect.setAttribute('fill', '#2ecc71');
// 可以用 CSS 添加动画
// rect { transition: fill 0.3s; }
</script>
WebGL 示例
<canvas id="glCanvas" width="200" height="200"></canvas>
<script>
const canvas = document.getElementById('glCanvas');
const gl = canvas.getContext('webgl');
// 顶点着色器
const vsSource = `
attribute vec4 aPosition;
void main() {
gl_Position = aPosition;
}
`;
// 片段着色器
const fsSource = `
precision mediump float;
uniform vec4 uColor;
void main() {
gl_FragColor = uColor;
}
`;
// 创建着色器
function createShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
return shader;
}
// 创建程序
const vertexShader = createShader(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fsSource);
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
// 定义三角形顶点
const vertices = new Float32Array([
0.0, 0.5, // 顶部
-0.5, -0.5, // 左下
0.5, -0.5 // 右下
]);
// 创建缓冲区
const buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
// 绑定顶点属性
const aPosition = gl.getAttribLocation(program, 'aPosition');
gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(aPosition);
// 设置颜色
const uColor = gl.getUniformLocation(program, 'uColor');
gl.uniform4f(uColor, 0.2, 0.6, 0.9, 1.0);
// 清除并绘制
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 3);
</script>
使用场景
Canvas 适合:
- 游戏开发(2D)
- 图像处理、滤镜
- 大量粒子效果
- 实时数据可视化
SVG 适合:
- 图标系统
- 图表(D3.js、ECharts)
- 地图
- 需要交互的矢量图形
- Logo、插画
WebGL 适合:
- 3D 游戏
- 3D 数据可视化
- 复杂特效
- 大规模数据渲染
关键点
- Canvas 是位图,适合像素级操作,放大会模糊
- SVG 是矢量图,元素是 DOM 节点,可直接绑定事件和 CSS
- WebGL 基于 GPU,性能最高,但需要着色器编程
- 元素少且需要交互选 SVG,大量图形或动画选 Canvas,3D 或高性能需求选 WebGL
- 实际项目中常用库:Canvas(Fabric.js)、SVG(D3.js)、WebGL(Three.js)
目录