Transform 实验室
CSS Transform 详解:从 2D 平移到 3D 透视的视觉魔法
T()
为什么 Transform 如此特殊?
CSS transform 是少数能触发 GPU 合成层的属性之一。与 top/left 等触发重排的属性不同,transform 直接在合成阶段操作,不触发布局重计算,因此动画极其流畅。
2D 变换矩阵
所有 2D transform 最终都会被编译为一个 3×3 的仿射变换矩阵:
┌ a c e ┐
│ b d f │
└ 0 0 1 ┘
其中 translate(tx, ty) 对应 e=tx, f=ty,scale(sx, sy) 对应 a=sx, d=sy,而 rotate(θ) 对应:
a = cos(θ) c = -sin(θ)
b = sin(θ) d = cos(θ)
变换原点 transform-origin
默认变换原点是元素中心 50% 50%。旋转和缩放都围绕这个点进行。修改 transform-origin 本质上是在变换前后各加一次平移:
M' = T(ox, oy) × M × T(-ox, -oy)
3D 变换与透视
3D 变换使用 4×4 矩阵。关键在于 perspective 属性 -- 它定义了观察者到 z=0 平面的距离,决定了 3D 透视的强度。
.card {
perspective: 1000px;
}
.card-inner {
transform: rotateY(60deg);
transform-style: preserve-3d;
}
perspective 的数学原理
透视投影将 3D 坐标 (x, y, z) 映射到 2D 屏幕:
x' = x × d / (d - z)
y' = y × d / (d - z)
其中 d 是透视距离。z 越大(越靠近观察者),放大的比例越大。
实践:卡片翻转动画
.flip-card {
perspective: 1000px;
}
.flip-inner {
transform-style: preserve-3d;
transition: transform 0.6s;
}
.flip-card:hover .flip-inner {
transform: rotateY(180deg);
}
.flip-front, .flip-back {
backface-visibility: hidden;
position: absolute;
}
.flip-back {
transform: rotateY(180deg);
}
性能最佳实践
- 优先使用 transform 和 opacity:它们不触发布局和绘制,直接在合成层处理
- will-change 提示:为即将动画的元素添加
will-change: transform - 避免嵌套 3D 上下文:过多的
preserve-3d会导致性能下降 - 使用 translate3d 强制 GPU 加速:
transform: translate3d(0,0,0)
Transform 的本质是矩阵乘法,而矩阵乘法的本质是线性变换的复合。理解了这一点,所有 CSS transform 的行为都有了数学解释。