1. 首页
  2. css

CSSHoudini对设置变换动画的意义

我已经玩了超过五年的CSS转换,有一件事一直困扰着我,那就是我不能单独动画transform链的组件。这篇文章将解释这个问题,旧的解决方法,新的魔法胡迪尼解决方案,最后,通过比用来说明概念的例子更好看的例子,为您提供一场赏心悦目的盛宴,让我们考虑一个在屏幕上水平移动的框的例子。这意味着一个div就HTML而言:

The CSS is also pretty straightforward. We give this box dimensions, a background并用margin将其水平放置在中间。
$d: 4em;.box {margin: .25*$d auto;width: $d; height: $d;background: #f90;}
接下来,借助于沿x轴的平移,我们将其向左移动半个视口(50vw),正面朝右):
transform: translate(-50vw);
现在方框的左半部分在屏幕外面。将平移的绝对量减少一半,使其完全位于视口中,同时再减少一半,我们假设一个完整的边长度(即$d或100%-请记住translate()函数中的%值与被平移元素的尺寸有关),使它甚至不再接触视口的左边缘。
transform: translate(calc(-1*(50vw – 100%)));
这将是我们的初始动画位置。
然后我们创建一组@keyframes,将长方体移动到相对于初始长方体的对称位置,而不进行平移,并在设置时引用它们animation:
$t: 1.5s;.box {/* same styles as before */animation: move $t ease-in-out infinite alternate;}@keyframes move {to { transform: translate(calc(50vw – 100%)); }}
这些都按预期工作,给我们提供了一个从左到右和从后移动的盒子:
但是这是一个非常无聊的动画,所以让我们让它更有趣。假设我们想把盒子缩小到15倍,当它在中间,两端有正常大小时。我们可以再添加一个关键帧:
50% { transform: scale(.1); }
盒子现在也可以缩放(演示),但是,由于我们添加了一个额外的关键帧,计时功能不再应用于整个动画,只适用于关键帧之间的部分。这使得我们的翻译在中间(在50%)缓慢,因为我们现在也有一个关键帧在那里。所以我们需要调整时间函数,在animation值和@keyframes中。在我们的例子中,既然我们想要一个ease-in-out,我们可以把它分成一个ease-in和一个ease-out。
.box {animation: move $t ease-in infinite alternate;}@keyframes move {50% {transform: scale(.1);animation-timing-function: ease-out;}to { transform: translate(calc(50vw – 100%)); }}
现在都可以了,但是如果我们想要不同的时间函数来进行转换和缩放呢?我们设置的计时功能意味着animation在开始时比较慢,中间比较快,最后又比较慢。如果我们想让它只适用于翻译,而不适用于比例尺呢?如果我们希望缩放在开始时快速发生,当它从1到.1,在中间缓慢发生,当它在.1左右,然后在结束时再次快速回到1,会怎么样?动画时间轴(直播)。
好吧,只是不可能为同一链中的不同变换函数设置不同的计时函数。我们不能让翻译在开始时变慢,缩放在中间变快,或者在中间变慢。至少,我们动画的是transform属性,它们是同一个transform链的一部分。旧的解决方法
当然有解决这个问题的方法。传统上,解决方案是将transform(以及animation)拆分为多个元素。这为我们提供了以下结构:

We move the width包装器上的属性。由于div元素在默认情况下是块元素,这也将确定其.box子元素的width,而无需我们显式设置它。我们将height保留在.box上,但是,由于子级的height(本例中的.box)也决定了其父级的height(本例中的包装器)。
我们还将margin、transform和animation属性上移。除此之外,我们切换回animation的ease-in-out计时功能。我们还将@keyframes的move集修改为最初的***集,这样我们就去掉了scale()。
.wrap {margin: .25*$d calc(50% – #{.5*$d});width: $d;transform: translate(calc(-1*(50vw – 100%)));animation: move $t ease-in-out infinite alternate;}@keyframes move {to { transform: translate(calc(50vw – 100%)); }}
我们创建了另一个@keyframes集,用于实际的.box元素。这是一个交替的animation产生振荡运动的持续时间的一半。
.box {height: $d;background: #f90;animation: size .5*$t ease-out infinite alternate;}@keyframes size { to { transform: scale(.1); } }
我们现在得到了我们想要的结果:
这是一个可靠的解决方案,不会添加太多额外的代码,更不用说在这个特殊的情况下,我们实际上不需要两个元素,我们只需要一个伪元素。但是如果我们的转换链变长了,我们别无选择,只能添加额外的元素. 在2018年,我们可以做得更好!胡迪尼解决方案,你们中的一些人可能已经知道CSS变量是不可设置动画的(我想任何一个没有发现的人)。如果我们尝试在***55***中使用它们,它们只会在两个值之间经过一半时间后从一个值切换到另一个值。
考虑振荡盒的初始示例(不涉及缩放)。假设我们尝试使用自定义属性***56***:
***57***
制作动画,不幸的是,这只会导致***58***的翻转,官方原因是浏览器无法知道自定义属性的类型(这对我来说没有意义,但我猜这并不重要)。
但我们可以忘记所有这些因为现在Houdini已经输入了图片,我们可以注册这样的自定义属性,这样我们就可以显式地给它们一个类型(the***59***)。
有关这方面的更多信息,请查看Serg Hospodarets的talk和slides。
***60***
***61***在规范的早期版本中是可选的,但是后来它变成了强制的,所以如果您发现一个老的胡迪尼演示,它不再工作了,很可能是因为它没有显式地设置***62***。
我们已经将***63***设置为***64***,因为我们必须将它设置为某个值,并且某个值必须是计算独立的值,也就是说,它不能依赖于我们可以在CSS中设置或更改的任何值最终的转换值取决于我们在CSS中设置的框的尺寸,***65***在这里无效。将***66***设置为***67***甚至不起作用,我们需要使用***68***来代替它。
***69***我们使用新方法得到的简单振荡盒(实时演示,需要Houdini支持)。
目前,这只在实验网络平台后面的Blink浏览器中起作用功能标志。这可以从***70***(或者,如果您使用Opera,***71***)启用:在Chrome中启用的实验性Web平台功能标志。
在所有其他浏览器中,我们仍然可以在***72***看到翻转。将此应用于我们的振荡和缩放演示意味着我们引入了两个自定义属性,一个是沿x轴的平移量(**73***),另一个是均匀缩放因子(**74***)。
**75***如下:
***76***新方法的振荡和缩放(现场演示,需要Houdini支持)。更好看的东西
一个简单的振荡和缩放方块并不是最令人兴奋的事情,所以让我们看看更好的演示吧!更多有趣的例子。左图:旋转的波浪形立方体网格。右图:弹跳的正方形。3D版从2D到3D,正方形变成了一个立方体,既然只有一个立方体不够有趣,那就让我们用一个完整的立方体网格吧!
我们认为***77***是我们的场景。在这个场景中,我们有一个立方体的三维集合(***78***)。这些多维数据集分布在***79***行和***80***列的网格上:
***81***)和多维数据集组上的行(***82***)索引。最初,我们将所有多维数据集的这两个索引都设置为***83***。
***84***
因为我们的多维数据集的数量等于每行的列数(***85***),所以在第一个***87***之后,我们将所有多维数据集的行索引设置为***86***。然后,对于第一个***88***之后的所有多维数据集,我们将行索引设置为***89***。以此类推,直到我们覆盖了所有的***90***行:
***91***
我们可以将它压缩成一个循环:
***92***然后再遇到另一个具有相同索引的多维数据集。因此,对于每个立方体,在它之后的第93个立方体将有相同的索引,我们将有一组这样的立方体,因此,我们可以跳过包含列索引为***97***的多维数据集的第一组-无需将***98***再次设置为它已经具有的相同值。)
***99***
这也可以在循环中压缩:
***100***变换,如下图所示,其中每个多维数据集在屏幕平面和距离是在***101***点之间测量的(默认情况下,这些点位于***102***,因此位于屏幕平面的正方形立方体部分中间):
0)和第一行(索引***103***)。第二列(索引***104***)上的所有项目均按和边长水平偏移。第三列(索引***105***)上的所有项目水平偏移两个边长。一般

CSSHoudini对设置变换动画的意义 为WP2原创文章,链接:https://www.wp2.cn/css/csshoudini%e5%af%b9%e8%ae%be%e7%bd%ae%e5%8f%98%e6%8d%a2%e5%8a%a8%e7%94%bb%e7%9a%84%e6%84%8f%e4%b9%89/