CSS 矩阵变换的实践
内圣外王之道,暗而不明,郁而不发,天下之人各为其所欲焉以自为方。
之前用过的 css transform 形变,只会熟练的使用 旋转 rotate 缩放 scale 斜切 skew 位移 translate 这些基础的属性。
近来想尝试一下高端的 矩阵变换,虽然开篇就是专业的坐标系云云,险些劝退,但是不要紧,弄清楚这几个值就还好。
定义
transform: matrix(a, b, c, d, tx, ty)
这里的 a b 等就是基础的变换的组合,相当于是
matrix(scaleX(), skewY(), skewX(), scaleY(), translateX(), translateY())
然后就是填空了,把原来的基础变换放到对应的位置。
缩放和斜切是比例,位移是距离,默认情况,缩放比例是 1,斜切比例是 0,位移距离是 0。所以不变换的 matrix 就是
{
transform: matrix(1, 0, 0, 1, 0, 0);
}
实践
假设有一个正方形盒子,想将其变换为一个伪 3d 的效果
el
el1
el2
el3
首先将其拆解为三个面,由于要将其拼接成标准的 六边形,故而每一个都要是一个四边等长的菱形,然后其中的钝角是 120° 用来三分圆周。
先变换出第一个面,可以正方形的 x轴 压缩,然后在 y轴 方向向右下斜切。
el1
因为边长相等,变换后差集部分的三角形锐角为 120° - 90° ,通过三角函数计算 x轴 缩放的比例为
{
transform: scaleX(calc( cos(30deg) / 1));
}
然后 y 轴斜切的比例为
{
transform: skewY(calc( sin(30deg) / 1));
}
组合起来
.el1 {
transform: matrix(cos(30deg), sin(30deg), 0, 1, 0, 0);
}
第二个面相对于第一个,只需要向右上斜切即可得到对应的形状,然后做一下位移
el1
el2
el3
el2
.el2 {
transform: matrix(
cos(30deg),
sin(-30deg),
0,
1,
calc(cos(30deg) * 100),
calc(sin(30deg) * 100)
);
}
第三个面可以理解为,将第一个面旋转 -60度。注意一下,css 变换的 顺序 是从后往前。
所以要组合的话,就要先矩阵变换,然后再 z 轴旋转
el1
el2
el3
el3
.el3 {
transform: rotateZ(-60deg) matrix(cos(30deg), sin(30deg), 0, 1, 0, 0);
}
逆推
如果现在拿到了一个格式化了的 3D 盒子,想要将其顶面( el3 )变换回来标准的平面:
直接作用在组上变换:
- 先旋转 60度,使得顶面左边竖直
- 将盒子平移
- 将盒子 x轴 整体放大为原来的
1 / cos(30deg)倍 - 在放大的基础上再来斜切
el1
el2
el3
el1
el2
el3
.group-transform {
transform-origin: 0 0;
transform: matrix(
calc(1 / cos(30deg)),
calc(1 / cos(30deg) * sin(-30deg)),
0,
1,
100,
0
)
rotateZ(60deg);
}
致谢
- 感谢三角函数 为手动计算提供了数学基础;
- 感谢绘图软件和勤劳的处理器,在可视化操作的背后默默的进行着复杂的计算;