Canvas图形变换本质是操作坐标系,需用translate、rotate、scale、transform等方法协同实现旋转、翻转、倾斜;关键是以目标点为原点平移后再变换,并用save/restore管理状态。

Canvas 实现图形变换,核心是操作其 2D 渲染上下文的坐标系,而不是直接修改图形本身。旋转、翻转、倾斜这三类效果,都依赖 translate、rotate、scale 和 transform 等方法协同完成。关键在于理解:所有变换都是对坐标系的操作,且默认以画布左上角(0,0)为原点;若要绕图形自身中心或任意点变换,必须先平移原点。
旋转:绕指定点转动图形
Canvas 的 rotate() 只接受弧度值,且始终绕当前坐标系原点旋转。因此,想让一个矩形绕其中心旋转,需三步:
- 用 save() 保存当前状态,避免影响后续绘制
- 用 translate(x + width/2, y + height/2) 把原点移到矩形中心
- 调用 rotate(angle * Math.PI / 180)(角度转弧度),再绘制图形(此时坐标 (0,0) 就是中心)
- 最后用 restore() 恢复原始坐标系
例如:旋转一个宽 100、高 60、位于 (150,100) 的红色矩形 30 度:
ctx.save();ctx.translate(200, 130); // 150+50, 100+30
ctx.rotate(30 * Math.PI / 180);
ctx.fillStyle = 'red';
ctx.fillRect(-50, -30, 100, 60); // 以新原点为中心绘制
ctx.restore();
翻转:水平或垂直镜像
Canvas 没有直接的“flip”方法,但可用 scale() 实现镜像效果:
- 水平翻转:在平移至目标中心后,执行 scale(-1, 1),再绘制图形(x 坐标需取反)
- 垂直翻转:执行 scale(1, -1),y 坐标需取反
- 注意:scale 会同时缩放线宽、文字等,如需保持样式不变,应在 scale 前设置好 strokeStyle/fillStyle,并在 restore 后重置
示例:水平翻转同一矩形:
ctx.translate(200, 130);
ctx.scale(-1, 1);
ctx.fillStyle = 'blue';
ctx.fillRect(50, -30, 100, 60); // x 起始点变为 +50(因 scale(-1,1) 后 -50→50)
ctx.restore();
倾斜:使用 transform 实现斜切
Canvas 原生 API 不提供 skew() 方法(Android Canvas 有,但 Web Canvas 没有)。要实现倾斜(shear),必须手动构造仿射变换矩阵,用 transform(a, b, c, d, e, f) 或 setTransform(a, b, c, d, e, f)。
- 水平倾斜(X shear):矩阵为 [1, 0, k, 1, 0, 0],其中 k 是倾斜系数(如 0.3 表示 tanθ ≈ 0.3)
- 垂直倾斜(Y shear):矩阵为 [1, k, 0, 1, 0, 0]
- 若需绕某点倾斜,仍需先 translate 到该点,再 transform,再 translate 回去(或用 setTransform 配合复合计算)
简单水平倾斜示例(绕左上角):
ctx.save();ctx.transform(1, 0, 0.4, 1, 0, 0); // 水平 shear 系数 0.4
ctx.fillStyle = 'green';
ctx.fillRect(100, 50, 120, 80);
ctx.restore();
组合与状态管理是关键
多个变换叠加时,顺序直接影响结果(矩阵乘法不可交换):
- 常见安全顺序:translate → rotate → scale(或 translate → transform)
- 每次独立变换建议包裹在 save()/restore() 中,否则后续绘制会继承前序变换
- 用 resetTransform() 可快速清空所有变换(等价于 setTransform(1,0,0,1,0,0)),比 restore 更彻底,但不恢复 fillStyle 等样式
不复杂但容易忽略。


















