Canvas transform方法详解,掌握变换矩阵原理、倾斜效果和高级变换技巧。transform方法提供了最底层的矩阵变换能力,可以实现所有其他变换效果。
ctx.transform(a, b, c, d, e, f)
ctx.setTransform(a, b, c, d, e, f)
| 参数 | 说明 |
|---|---|
| a | 水平缩放 |
| b | 垂直倾斜 |
| c | 水平倾斜 |
| d | 垂直缩放 |
| e | 水平平移 |
| f | 垂直平移 |
Canvas使用3x3的变换矩阵:
| a c e |
| b d f |
| 0 0 1 |
坐标变换公式:
x' = a*x + c*y + e
y' = b*x + d*y + f
| 方法 | 说明 |
|---|---|
| transform() | 在当前变换基础上叠加新变换 |
| setTransform() | 重置变换矩阵后设置新变换 |
// transform累积
ctx.transform(1, 0, 0, 1, 100, 0) // 平移100
ctx.transform(1, 0, 0, 1, 50, 0) // 再平移50,总共150
// setTransform重置
ctx.setTransform(1, 0, 0, 1, 100, 0) // 平移100
ctx.setTransform(1, 0, 0, 1, 50, 0) // 重置后平移50,总共50
ctx.transform(1, 0, 0, 1, tx, ty)
// 等价于
ctx.translate(tx, ty)
const angle = Math.PI / 4
ctx.transform(Math.cos(angle), Math.sin(angle), -Math.sin(angle), Math.cos(angle), 0, 0)
// 等价于
ctx.rotate(angle)
ctx.transform(sx, 0, 0, sy, 0, 0)
// 等价于
ctx.scale(sx, sy)
倾斜(错切)是transform独有的能力:
// 水平倾斜
ctx.transform(1, 0, skewX, 1, 0, 0)
// 垂直倾斜
ctx.transform(1, skewY, 0, 1, 0, 0)
使用矩阵组合多个变换:
// 组合:缩放 + 旋转 + 平移
const scale = 2
const angle = Math.PI / 4
const tx = 100
const ty = 50
ctx.transform(
scale * Math.cos(angle),
scale * Math.sin(angle),
-scale * Math.sin(angle),
scale * Math.cos(angle),
tx,
ty
)
使用getTransform方法获取当前变换矩阵:
const matrix = ctx.getTransform()
console.log(matrix.a, matrix.b, matrix.c, matrix.d, matrix.e, matrix.f)
const TransformMatrix = {
identity() {
return { a: 1, b: 0, c: 0, d: 1, e: 0, f: 0 }
},
translate(tx, ty) {
return { a: 1, b: 0, c: 0, d: 1, e: tx, f: ty }
},
rotate(angle) {
const cos = Math.cos(angle)
const sin = Math.sin(angle)
return { a: cos, b: sin, c: -sin, d: cos, e: 0, f: 0 }
},
scale(sx, sy) {
return { a: sx, b: 0, c: 0, d: sy, e: 0, f: 0 }
},
multiply(m1, m2) {
return {
a: m1.a * m2.a + m1.c * m2.b,
b: m1.b * m2.a + m1.d * m2.b,
c: m1.a * m2.c + m1.c * m2.d,
d: m1.b * m2.c + m1.d * m2.d,
e: m1.a * m2.e + m1.c * m2.f + m1.e,
f: m1.b * m2.e + m1.d * m2.f + m1.f
}
},
apply(ctx, m) {
ctx.setTransform(m.a, m.b, m.c, m.d, m.e, m.f)
}
}
矩阵乘法顺序
transform的矩阵乘法是右乘,顺序与直觉相反。
累积效应
transform会累积,使用setTransform重置。
性能考虑
复杂变换时,直接使用矩阵比多次调用基本变换更高效。
精度问题
多次矩阵运算可能产生精度误差,定期重置。