利用单个 transform 属性对 CSS transform 进行更精细的控制
CSS transform
属性
如需对元素应用转换,请使用 CSS transform
属性。该属性接受一个或多个接一个应用的 <transform-function>
。
.target {
transform: translateX(50%) rotate(30deg) scale(1.2);
}
目标元素在 X 轴上平移 50%,旋转 30 度,并最终放大到 120%。
虽然 transform
属性可以正常运行,但当您需要单独更改其中的任何值时,它就会变得有点繁琐。
若要更改悬停时的缩放比例,您必须复制转换属性中的所有函数,即使它们的值保持不变。
.target:hover {
transform: translateX(50%) rotate(30deg) scale(2); /* Only the value of scale() changed */
}
各个转换属性
Chrome 104 中装载的是 CSS 转换的各个属性。属性包括 scale
、rotate
和 translate
,可用于单独定义转换的这些部分。
这样,Chrome 浏览器将加入已支持这些属性的 Firefox 和 Safari。
使用单个属性重写上面的 transform
示例,您的代码段将变为:
.target {
translate: 50% 0;
rotate: 30deg;
scale: 1.2;
}
顺序很重要
原始 CSS transform
属性与新属性之间的一个主要区别在于应用声明的转换的顺序。
借助 transform
,转换函数会按照编写顺序应用:从左(外)到右(内)。
对于各个转换属性,其顺序并不是它们的声明顺序。顺序始终相同:首先是 translate
(外侧),然后是 rotate
,最后是 scale
(内侧)。
这意味着以下两个代码段会得到相同的结果:
.transform--individual {
translate: 50% 0;
rotate: 30deg;
scale: 1.2;
}
.transform--individual-alt {
rotate: 30deg;
translate: 50% 0;
scale: 1.2;
}
在这两种情况下,目标元素将首先在 X 轴上按 50%
平移,再按 30deg
旋转,最后按 1.2
进行缩放。
如果将其中一个转换属性与 transform
属性一起声明,则先应用各个转换(translate
、rotate
,然后是 scale
),最后应用 transform
(内部)。如需了解详情,请参阅定义应如何计算转换矩阵的规范。
动画
添加这些属性的主要原因是使动画变得更简单。假设您要为某个元素添加动画效果,如下所示:
使用 transform
如需使用 transform
实现此动画,您必须计算所有已定义的转换之间的所有中间值,并在每个关键帧中添加这些值。例如,如需在 10% 标记处进行旋转,还必须计算其他转换的值,因为 transform
属性需要所有这些转换的值。
生成的 CSS 代码将如下所示:
@keyframes anim {
0% { transform: translateX(0%); }
5% { transform: translateX(5%) rotate(90deg) scale(1.2); }
10% { transform: translateX(10%) rotate(180deg) scale(1.2); }
90% { transform: translateX(90%) rotate(180deg) scale(1.2); }
95% { transform: translateX(95%) rotate(270deg) scale(1.2); }
100% { transform: translateX(100%) rotate(360deg); }
}
.target {
animation: anim 2s;
animation-fill-mode: forwards;
}
使用各个转换属性
通过单个转换属性,编写代码会变得更容易。您可以单独定位每个转换,而不是将所有转换从关键帧拖动到关键帧。您也不再需要计算介于两者之间的所有值。
@keyframes anim {
0% { translate: 0% 0; }
100% { translate: 100% 0; }
0%, 100% { scale: 1; }
5%, 95% { scale: 1.2; }
0% { rotate: 0deg; }
10%, 90% { rotate: 180deg; }
100% { rotate: 360deg; }
}
.target {
animation: anim 2s;
animation-fill-mode: forwards;
}
使用各个转换属性和多个关键帧
如需使代码模块化,您可以将每个子动画拆分为一组自己的关键帧。
@keyframes move {
0% { translate: 0% 0; }
100% { translate: 100% 0; }
}
@keyframes scale {
0%, 100% { scale: 1; }
5%, 95% { scale: 1.2; }
}
@keyframes rotate {
0% { rotate: 0deg; }
10%, 90% { rotate: 180deg; }
100% { rotate: 360deg; }
}
.target {
animation: move 2s, scale 2s, rotate 2s;
animation-fill-mode: forwards;
}
得益于此拆分,您可以根据需要应用每组单独的关键帧,因为 transform
属性(现已成为单独的属性)不再相互覆盖。在此之上,您可以为每种转换指定不同的时间,而无需重写整段代码。
性能
使用这些新属性的动画与现有 transform
属性的动画一样高效。
translate
、rotate
和 scale
的动画在合成器上运行的方式与 transform
的动画相同,因此它们有利于提升动画性能,与 transform
相同。
这些新属性也适用于 will-change
属性。一般来说,最好避免过度使用 will-change
,方法是针对最少数量的元素使用它,并尽可能缩短使用时间。但最好尽量具体。例如,如果您使用 will-change
通过 rotate
和 filter
属性优化动画,则应使用 will-change: rotate, filter
进行声明。如果您要为 rotate
和 filter
添加动画效果,那么这比使用 will-change: transform, filter
稍好一点,因为当您使用 will-change
时,Chrome 提前创建的某些数据结构对于 transform
和 rotate
有所不同。