创建交错动画的不同方法

Avatar of Daniel Benmore
Daniel Benmore

DigitalOcean 为您旅程的每个阶段提供云产品。 立即开始使用 价值 200 美元的免费积分!

动画元素,在最基本的情况下,相当简单。 定义关键帧。 命名动画。 在元素上调用它。

但有时我们需要更复杂的东西才能获得事物移动方式的正确“感觉”。 例如,均衡器可能会在每个条形上使用相同的动画,但它们是交错的,给人以独立动画的错觉。

查看 Pen
Apple Music 音频均衡器在 SVG 中
由 Geoff Graham (@geoffgraham)
CodePen 上。

我最近正在构建一个仪表板,并且希望其中一个窗口小部件中的项目以交错动画的方式流入视图。

就像上面的均衡器一样,我开始使用 :nth-child 路线。 我使用无序列表 (<ul>) 作为父容器,为它提供一个类并使用 :nth-child 伪选择器通过 animaton-delay 来偏移每个列表项。

.my-list li {
  animation: my-animation 300ms ease-out;
}

.my-list li:nth-child(1) {
  animation-delay: 100ms;
}

.my-list li:nth-child(2) {
  animation-delay: 200ms;
}

.my-list li:nth-child(3) {
  animation-delay: 300ms;
}

/* and so on */

这种技术确实可以很好地交错项目,特别是在您知道列表中将有多少项目的情况下。 但是,当项目数量不可预测时,事情就会崩溃,这正是我为仪表板构建的小部件的情况。 我真的不想每次列表中的项目数量发生变化时都回到这段代码,所以我敲出了一个快速 Sass 循环,它可以处理最多 50 个项目并为每个项目递增动画延迟。

.my-list {
  li {
    animation: my-animation 300ms ease-out;
      
    @for $i from 1 through 50 {
      &:nth-child(#{$i}) {
        animation-delay: 100ms * $i;
      }
    }
  }
}

应该可以了! 但是,感觉太 hacky 了。 当然,它不会给文件增加太多重量,但您知道编译后的 CSS 将包含很多未使用的选择器,例如 nth-child(45)

一定有更好的方法。 通常情况下,我会使用 JavaScript 来查找所有项目并添加延迟,但是……这次我花了一些时间探索,看看是否有一种方法可以使用 CSS 来完成。

CSS 计数器怎么样?

我想到的第一件事是将 CSS 计数器与 calc() 函数结合使用。

.my-list {
  counter-reset: my-counter;
}

.my-list li {
  counter-increment: my-counter;
  animation-delay: calc(counter(my-counter) * 100ms);
}

不幸的是,这行不通,因为规范说 计数器不能在 calc() 中使用)。

calc() 表达式的组成部分可以是文字值或 attr()calc() 表达式。

事实证明,有些人喜欢这个想法,但它还没有超出 草案阶段

数据属性怎么样?

在阅读了规范中的那段摘录后,我了解到 calc() 可以使用 attr()。 而且,根据 CSS 值和单位规范)。

在 CSS3 中,attr() 表达式可以返回多种不同类型

这让我想到;也许数据属性可以做到这一点。

<ul class="my-list">
  <li data-count="1"></li>
  <li data-count="2"></li>
  <li data-count="3"></li>
  <li data-count="4"></li>
</ul>
.my-list li {
  animation-delay: calc(attr(data-count) * 150ms);
}

但我的希望破灭了,因为对它的浏览器支持实在太糟糕了!

此浏览器支持数据来自 Caniuse,它提供了更多详细信息。 数字表示浏览器从该版本开始支持该功能。

桌面

ChromeFirefoxIEEdgeSafari

移动设备 / 平板电脑

Android ChromeAndroid FirefoxAndroidiOS Safari

所以,回到起点。

自定义属性怎么样?

我想到的下一个想法是使用 CSS 自定义属性。 它并不漂亮,但它确实有效 🙂

查看 Pen
CSS 变量动画顺序
由 Dan Benmore (@dbenmore)
CodePen 上。

事实证明它非常灵活。 例如,动画可以反转。

查看 Pen
CSS 变量反转动画顺序
由 Dan Benmore (@dbenmore)
CodePen 上。

它还可以做一些完全随机的事情,并同时动画化元素。

查看 Pen
CSS 变量随机动画顺序
由 Dan Benmore (@dbenmore)
CodePen 上。

我们甚至可以更进一步,做一个对角线挥动。

查看 Pen
使用 CSS 属性/变量设置动画交错
由 Dan Benmore (@dbenmore)
CodePen 上。

浏览器支持并不差(戳戳 Internet Explorer)。

此浏览器支持数据来自 Caniuse,它提供了更多详细信息。 数字表示浏览器从该版本开始支持该功能。

桌面

ChromeFirefoxIEEdgeSafari
49311610

移动设备 / 平板电脑

Android ChromeAndroid FirefoxAndroidiOS Safari
12712712710.0-10.2

CSS 的一大优点是它 会忽略它不理解的东西,这得益于 层叠。 这意味着所有内容都将一起动画化进入视图。 如果您不喜欢,可以添加一个功能查询来覆盖默认动画。

.my-list li {
  animation: fallback-animation;
}

@supports (--variables) {
  .my-list li {
    animation: fancy-animation;
    animation-delay: calc(var(--animation-order) * 100ms);
  }
}

纯 CSS FTW

我越停下来问自己是否需要 JavaScript,就越惊讶于 CSS 本身能做些什么。 当然,如果 CSS 计数器可以在 calc() 函数中使用,那将是一个非常优雅的解决方案。 但目前,内联自定义属性提供了一种强大且灵活的方式来解决这个问题。