jjzjj

了解一下全新的CSS动画合成属性 Animation-Composition

XboxYan 2023-11-07 原文

介绍一个在Chrome 112​上刚刚正式推出的 CSS 动画合成属性:animation-composition。

​https://developer.mozilla.org/en-US/docs/Web/CSS/animation-composition​[1]

日后非常有用的一个特性,快来了解一下吧

一、从 CSS 抛物线运动说起

众所周知,抛物线运动是一个水平方向上匀速、垂直方向上匀加速的合成运动

这个其实用 CSS 动画也很好实现,水平和垂直两个方向的位移动画分别用不同的动画缓存函数。

有兴趣的可以参考张鑫旭的这篇文章:这回试试使用CSS实现抛物线运动效果[2]。

这里简单介绍一下。

实现这样的效果需要一个嵌套结构。

<div class="ball-x">
<div class="ball-y"></div>
</div>

然后里外设置不同的动画缓冲函数。

.ball-x { 
animation-timing-function: linear; /*匀速直线运动*/
}
.ball-y {
animation-timing-function: cubic-bezier(.55, 0, .85, .36); /*大致匀加速运动*/
}

运动分解效果如下:

那么问题来了,为啥这里需要用到两层标签呢?仅仅为了分解水平运动和垂直运动吗?如果只使用一层标签会怎么样?

这个稍后再说。

二、动画合成属性

现在来介绍今天的主角。首先看语法,还是非常简单的。

/* 单个值 */
animation-composition: replace;
animation-composition: add;/*追加*/
animation-composition: accumulate;/*混合*/
/* 多个值,暂不讨论 */
animation-composition: replace, add;
animation-composition: add, accumulate;
animation-composition: replace, add, accumulate;

主要是这 3 个关键词:

  • replace:覆盖(默认值)。动画会覆盖原有属性。
  • add:追加。动画追加到原有属性后面。
  • accumulate:累加。动画会和原有属性相同的部分进行累加。

光看语法和描述可能不知道是做什么的,特别是add和accumulate,差异非常微妙,直接看一个例子。

假设有一个元素,默认有一些样式。

div{
transform-origin: 50% 50%;
transform: translateX(50px) rotate(45deg);
}

然后,给一个动画,关键帧是这样的。

@keyframes adjust {
to {
transform: translateX(100px);
}
}

下面是 3 个关键词的效果对比。

demo参见 ​https://codepen.io/web-dot-dev/pen/VwGRBVX​[3]。

可以从动画运行的终点看出这几种合成的差异。

第一个replace,也就是默认效果。其实就是直接将transform中的translateX(50px) rotate(45deg)变成了translateX(100px)。

第二个add。可以理解成直接在transform后追加,也就是最后变成了translateX(50px) rotate(45deg) translateX(100px),等同于先向右移动50px,然后旋转45deg,再向右移动100px。下面是拆解过程(注意旋转轴)。

第三个accumulate。可以理解成将已有的translateX(50px)累加,最后结果是translateX(150px) rotate(45deg)。

怎么样,这几种差异明白了吗?

当然这些动画合成都是针对于相同的属性而言,对于不同的属性,本来就没有产生任何干扰,自然不会用到这个特性。

三、再来看抛物线运动

现在回过头来看前面那个例子。如果只用一层标签如何实现?

假设水平、垂直两个方向的动画关键帧是这样的。

@keyframes ballMoveX {
100%{
transform: translateX(300px)
}
}
@keyframes ballMoveY {
100% {
transform: translateY(300px)
}
}

然后小球将这两个动画合起来。

.ball{
animation:
ballMoveX 1s linear infinite alternate,
ballMoveY 1s cubic-bezier(.55, 0, .85, .36) infinite alternate;
}

可以得到一个很奇怪的动画。

原因其实是这两个属性冲突了,后面的动画覆盖了前面的,导致动画的结束点其实是translateY(300px)。

像这种情况下,用动画合成属性就非常合适了。

.ball{
...
animation-composition: add; /*accumulate也行*/
}

add和accumulate都行,因为translateX和translateY并不能累加,只能追加。

效果如下:

这样就得到了正常的抛物线运动了。

完整代码可以查看以下任意链接:

  • CSS animation-composition (juejin.cn)[4]
  • CSS animation-composition (runjs.work)[5]
  • CSS animation-composition (codepen.io)[6]

四、兼容性和总结

提一下兼容性。这方面 Safari居然跑在了前头,然后Chrome也是最近得到了正式支持,Firefox目前仍然是实验支持,不过离正式支持也不远了。也就是说这个特性以后一定会全兼容,也不用担心学着学着突然都放弃了。兼容性列表如下:

相信大家已经对动画合成有了一定的了解,下面总结一下要点:

可以用一杯水来做比方

  1. replace:替换。将这杯水倒掉,然后倒进一杯油。
  2. add:追加(叠加)。在这杯水上倒入一些油,油覆盖在了水上。
  3. accumulate:累加(混合)。在这杯水倒入奶茶,里面都有水,混合在了一起。

参考资料

​[1]https://developer.mozilla.org/en-US/docs/Web/CSS/animation-composition: https://developer.mozilla.org/en-US/docs/Web/CSS/animation-composition。

[2]这回试试使用CSS实现抛物线运动效果: https://www.zhangxinxu.com/wordpress/2018/08/css-css3-抛物线动画/。

[3]https://codepen.io/web-dot-dev/pen/VwGRBVX: https://codepen.io/web-dot-dev/pen/VwGRBVX。

[4]CSS animation-composition (juejin.cn): https://code.juejin.cn/pen/7224474156631326775。

[5]CSS animation-composition (runjs.work): https://runjs.work/projects/2ff7e7d8c5454f37。

[6]CSS animation-composition (codepen.io): https://codepen.io/xboxyan/pen/bGmByXN。

有关了解一下全新的CSS动画合成属性 Animation-Composition的更多相关文章

  1. ruby - capybara field.has_css?匹配器 - 2

    我在MiniTest::Spec和Capybara中使用以下规范:find_field('Email').must_have_css('[autofocus]')检查名为“电子邮件”的字段是否具有autofocus属性。doc说如下:has_css?(path,options={})ChecksifagivenCSSselectorisonthepageorcurrentnode.据我了解,字段“Email”是一个节点,因此调用must_have_css绝对有效!我做错了什么? 最佳答案 通过JonasNicklas得到了答案:No

  2. ruby-on-rails - 如果为空或不验证数值,则使属性默认为 0 - 2

    我希望我的UserPrice模型的属性在它们为空或不验证数值时默认为0。这些属性是tax_rate、shipping_cost和price。classCreateUserPrices8,:scale=>2t.decimal:tax_rate,:precision=>8,:scale=>2t.decimal:shipping_cost,:precision=>8,:scale=>2endendend起初,我将所有3列的:default=>0放在表格中,但我不想要这样,因为它已经填充了字段,我想使用占位符。这是我的UserPrice模型:classUserPrice回答before_val

  3. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  4. ruby - 多个属性的 update_column 方法 - 2

    我有一个具有一些属性的模型:attr1、attr2和attr3。我需要在不执行回调和验证的情况下更新此属性。我找到了update_column方法,但我想同时更新三个属性。我需要这样的东西:update_columns({attr1:val1,attr2:val2,attr3:val3})代替update_column(attr1,val1)update_column(attr2,val2)update_column(attr3,val3) 最佳答案 您可以使用update_columns(attr1:val1,attr2:val2

  5. ruby - Nokogiri 剥离所有属性 - 2

    我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog

  6. ruby-on-rails - Rails 模型——非持久类成员或属性? - 2

    对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs

  7. css - 用 watir 检查标签类? - 2

    我有一个div,它根据表单是否正确提交而改变。我想知道是否可以检查类的特定元素?开始元素看起来像这样。如果输入不正确,添加错误类。 最佳答案 试试这个:browser.div(:id=>"myerrortest").class_name更多信息:http://watir.github.com/watir-webdriver/doc/Watir/HTMLElement.html#class_name-instance_method另一种选择是只查看具有您期望的类的div是否存在browser.div((:id=>"myerrortes

  8. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  9. Unity 3D 制作开关门动画,旋转门制作,推拉门制作,门把手动画制作 - 2

    Unity自动旋转动画1.开门需要门把手先动,门再动2.关门需要门先动,门把手再动3.中途播放过程中不可以再次进行操作觉得太复杂?查看我的文章开关门简易进阶版效果:如果这个门可以直接打开的话,就不需要放置"门把手"如果门把手还有钥匙需要旋转,那就可以把钥匙放在门把手的"门把手",理论上是可以无限套娃的可调整参数有:角度,反向,轴向,速度运行时点击Test进行测试自己写的代码比较垃圾,命名与结构比较拉,高手轻点喷,新手有类似的需求可以拿去做参考上代码usingSystem.Collections;usingSystem.Collections.Generic;usingUnityEngine;u

  10. ruby - Chef Ruby 遍历 .erb 模板文件中的属性 - 2

    所以这可能有点令人困惑,但请耐心等待。简而言之,我想遍历具有特定键值的所有属性,然后如果值不为空,则将它们插入到模板中。这是我的代码:属性:#===DefaultfileConfigurations#default['elasticsearch']['default']['ES_USER']=''default['elasticsearch']['default']['ES_GROUP']=''default['elasticsearch']['default']['ES_HEAP_SIZE']=''default['elasticsearch']['default']['MAX_OP

随机推荐