Canvas 的 transform 方法需通过手动构造斜切矩阵实现斜切效果,即用 ctx.transform(a, b, c, d, e, f) 设置 a=1、d=1、b=tan(β)、c=tan(α),结合 setTransform 重置矩阵、坐标变换与 save/restore 隔离作用域来精准控制。

Canvas 的 transform 方法本身不直接提供“斜切”(skew)的独立接口,但可以通过设置变换矩阵(setTransform 或 transform)手动构造斜切矩阵来实现。关键在于理解 2D 变换矩阵结构,并用 ctx.transform(a, b, c, d, e, f) 注入斜切分量。
斜切矩阵的数学原理
Canvas 使用 3×2 仿射变换矩阵表示为:
[a c e]<br> [b d f]
其中左上 2×2 子矩阵控制线性变换(缩放、旋转、斜切),(e,f) 是平移量。
标准斜切(沿 x 轴倾斜 α,沿 y 轴倾斜 β)对应的矩阵为:a = 1, b = tan(β), c = tan(α), d = 1, e = 0, f = 0
例如:x 方向斜切 30° → c = Math.tan(30 * Math.PI / 180) ≈ 0.577;y 方向斜切 15° → b = Math.tan(15 * Math.PI / 180) ≈ 0.268。
用 transform() 实现可交互斜切
将斜切参数动态绑定到用户操作(如拖拽、滑块),实时更新矩阵:
- 监听鼠标/触摸事件获取偏移量,映射为角度或 tan 值
- 每次重绘前调用
ctx.setTransform(1, b, c, 1, 0, 0)重置并应用新斜切(推荐setTransform避免矩阵叠加累积误差) - 绘制图形时无需额外调整坐标,所有顶点自动按当前变换处理
示例:水平拖拽控制 x 斜切强度
let skewX = 0;
canvas.addEventListener('mousemove', e => {
const rect = canvas.getBoundingClientRect();
skewX = (e.clientX - rect.left) / canvas.width * 1.2 - 0.6; // 映射到 -0.6 ~ 0.6
});
function draw() {
ctx.setTransform(1, 0, skewX, 1, 0, 0); // 仅斜切x,无平移
ctx.fillRect(100, 100, 200, 100);
}结合其他变换的注意事项
斜切常需与平移、缩放、旋转组合使用。注意顺序敏感性:
- 先斜切再平移:用
transform(1, 0, c, 1, tx, ty) - 先平移再斜切(更常见):先
translate(tx, ty),再transform(1, 0, c, 1, 0, 0) - 避免连续
transform()叠加——它在当前矩阵基础上相乘,易导致意外复合效果;优先用setTransform(1, 0, c, 1, tx, ty)显式设定完整矩阵
响应式与坐标系对齐技巧
斜切后图形可能“跑出”预期位置,尤其在响应式布局中:
- 斜切中心默认是 Canvas 原点 (0,0),若想绕图形中心斜切,先
translate(cx, cy),再斜切,最后translate(-cx, -cy) - 用
ctx.save()/ctx.restore()隔离变换作用域,防止影响后续绘制 - 调试时可用
ctx.strokeStyle = 'red'; ctx.strokeRect(0, 0, 10, 10)标记原点,观察变换效果
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











