Canvas、SVG、WebGL 对比

三种浏览器图形技术的区别和使用场景

问题

Canvas、SVG、WebGL 有什么区别?分别适合什么场景?

解答

对比表格

特性CanvasSVGWebGL
渲染方式位图(像素)矢量(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)