首页 / HTML5 入门教程 / Canvas 变换与合成

HTML5 入门教程

Canvas 变换与合成

本教程共 110 篇 · 第 84 篇 · 更新于 2026-07-28 · 约 4 分钟阅读

HTML5HTML5 入门教程Canvas变换旋转缩放合成

84. Canvas 变换与合成

本节目标:掌握 Canvas 的坐标变换(平移、旋转、缩放)和图形合成模式。

Canvas 的变换功能让你不用重新计算坐标,就能画出旋转、缩放、偏移的图形。这在做动画和游戏时特别有用。

平移:translate

translate(x, y) 把坐标原点移动到新的位置。

ctx.fillStyle = 'blue';
ctx.fillRect(10, 10, 50, 50); // 原始位置

ctx.translate(100, 100);     // 原点移到 (100, 100)
ctx.fillStyle = 'red';
ctx.fillRect(10, 10, 50, 50); // 实际画在 (110, 110)

平移之后,所有后续绘制的坐标都相对于新原点。

Tip

平移常用于把旋转中心移到图形中心。比如画一个绕中心旋转的矩形,先平移到中心点,再旋转,然后画矩形。

旋转:rotate

rotate(angle) 旋转坐标系,角度用弧度。

ctx.translate(100, 100);       // 把原点移到 (100, 100)
ctx.rotate(Math.PI / 4);      // 旋转 45 度
ctx.fillStyle = 'green';
ctx.fillRect(0, 0, 80, 40);    // 画一个旋转了 45 度的矩形

旋转是绕原点进行的,所以通常配合 translate 使用。

缩放:scale

scale(x, y) 在 X 和 Y 方向上缩放。

ctx.scale(2, 1); // X 方向放大 2 倍,Y 方向不变
ctx.fillRect(50, 50, 40, 40); // 实际画出 80x40 的矩形

缩放值大于 1 是放大,小于 1 是缩小,负值会翻转。

保存和恢复状态

变换操作会累积。画完一个旋转的图形后,坐标系还是旋转的。这时候需要恢复。

ctx.save();           // 保存当前状态
ctx.translate(100, 100);
ctx.rotate(Math.PI / 6);
ctx.fillRect(0, 0, 50, 50);
ctx.restore();        // 恢复到 save 时的状态

// 现在坐标系又回到原始状态
ctx.fillRect(0, 0, 30, 30); // 正常绘制

save() 把当前状态压入栈,restore() 从栈中弹出。可以嵌套使用。

变换矩阵:transform 和 setTransform

除了上面三个方法,Canvas 还提供了直接操作变换矩阵的接口:

ctx.transform(a, b, c, d, e, f);

参数对应一个 3x3 矩阵(实际只用 6 个值)。大多数情况下用 translaterotatescale 就够了。

setTransform 会重置变换矩阵再应用新的变换,不受之前变换的影响:

ctx.setTransform(1, 0, 0, 1, 0, 0); // 重置为单位矩阵

图形合成:globalCompositeOperation

这个属性控制新图形和已有图形的合成方式。

ctx.fillStyle = 'red';
ctx.fillRect(50, 50, 100, 100);

ctx.globalCompositeOperation = 'destination-over';
ctx.fillStyle = 'blue';
ctx.fillRect(80, 80, 100, 100);

常用合成模式:

模式效果
source-over默认,新图形覆盖旧图形
destination-over旧图形覆盖新图形
source-in只显示新旧重叠部分的新图形
destination-out擦除新旧重叠部分的旧图形
lighter重叠部分颜色叠加变亮
xor重叠部分变透明
Note

destination-out 模式常用来”擦除”部分画面,实现橡皮擦效果。

完整示例:画一个时钟刻度

const centerX = 200, centerY = 200;

// 画表盘
ctx.beginPath();
ctx.arc(centerX, centerY, 150, 0, Math.PI * 2);
ctx.stroke();

// 画刻度
for (let i = 0; i < 12; i++) {
  ctx.save();
  ctx.translate(centerX, centerY);
  ctx.rotate((Math.PI * 2 / 12) * i);
  ctx.beginPath();
  ctx.moveTo(130, 0);
  ctx.lineTo(145, 0);
  ctx.lineWidth = 3;
  ctx.stroke();
  ctx.restore();
}

小结

  • translate 平移坐标系原点
  • rotate 旋转坐标系(弧度)
  • scale 缩放坐标系
  • save / restore 保存和恢复状态
  • globalCompositeOperation 控制图形合成模式
  • 变换通常配合使用,先平移再旋转是常见套路