网络动画API与CSS的对比

295 阅读11分钟

网页动画是网页设计的一个流行的补充,导致了许多JavaScript动画库的发展,包括Framer MotionGreenSock。然而,许多开发者仍然选择使用CSS过渡、CSS动画或JavaScript Web Animations API(WAAPI)从头开始创建网页动画。

在本教程中,我们将深入介绍这三种方法,通过相关演示学习如何使用每一种方法。我们将比较每一种方法,并讨论使Web Animations API在我看来被低估的许多好处。让我们开始吧!

CSS转场

CSS过渡允许我们将一个CSS属性从一个状态无缝地改变到另一个状态。例如,假设我们想把一个元素的background-color 属性的值从黑色改为红色。自然,这种变化会立即发生,但是,CSS过渡让我们可以控制这个过程的某些方面。

例如,我们可以决定何时开始变化,使哪些属性产生动画,以及动画将运行多长时间。要使其成为动画,该属性必须包含在CSS可动画的属性列表中。

属性

让我们回顾一下创建CSS过渡所需的CSS属性。

  • transition-property :我们要应用过渡的CSS属性
  • transition-duration :过渡应该运行的时间长度
  • transition-delay :动画开始前要等待多长时间
  • transition-timing-function :过渡的速度

transition-timing-function 是线性的,速度增加,或速度减少。通常情况下,transition-timing-function 是一个确定中间点的CSS属性值的函数,或者是一个与该函数等价的关键词。

你可以使用transition 这个速记属性来代替上述的四个属性。

.element {
  transition: <property> <duration> <timing-function> <delay>;
}

演示

现在,让我们看看CSS转换的实际效果吧在下面的CodePen中,当用户在显示器上悬停时,背景颜色将从黑色变为红色。

请看Udoh Idorenyin(@idorenyinudoh)
CodePen上的Pen
css转场测试。

多个动画

在下面的演示中,你会看到我们如何通过用逗号分隔过渡属性的值来在多个CSS属性中应用CSS过渡。

参见CodePen上Udoh Idorenyin(@idorenyinudoh)
的Pen
css过渡测试2。

现在我们已经熟悉了CSS过渡,让我们来看看CSS动画的情况。

CSS动画

CSS动画让我们的动画变得更有趣一些。我们需要一个@keyframes CSS at-rule,它规定了动画开始时、动画结束时和动画周期内的CSS规则。我们还需要一个初始化CSS动画的规则。

属性

让我们来看看创建一个CSS动画所需要的属性。

  • animation-name:@keyframes at-rule的名称
  • animation-play-state: 指定动画是否是runningpaused
  • animation-direction: 指定动画的方向
  • animation-iteration-count :动画将完成的周期数
  • animation-fill-mode :动画在执行前后如何对元素应用样式

如果animation-iteration-count 被设置为infinite ,动画将连续播放。如果animation-fill-mode 被设置为forward ,元素将保留最后一个关键帧的样式。如果设置为backward ,在动画开始之前,第一个关键帧的造型会应用到元素上。

animation-delay 是应用和播放动画之间的时间。它类似于CSS过渡中的transition-delayanimation-duration 是动画完成一个周期的时间。它的等价物是transition-duration

最后,animation-timing-function 表示一个动画在其周期内的进展情况。它的等价物是transition-timing-function 。与CSS过渡一样,CSS动画也有一个animation 的缩写,用来处理这些属性。

.element {
  animation: <name> <duration> <timing-function> <delay> <iteration-count> <direction> <fill-mode>;
}

演示

为了了解CSS动画的工作原理,让我们重新制作上面的演示,并将一个对象的背景颜色从黑色改为红色。

请看CodePen上Udoh Idorenyin(@idorenyinudoh)
的Pen
css动画测试。

你可能已经注意到与CSS过渡的几个关键区别。其一,动画立即开始,而不是由用户初始化。CSS动画属性可以利用@keyframes at-rule,当它可用于运行元素时。

然而,在CSS转换中,定义动画结束状态的规则必须在一个不同于元素默认声明的声明中。出于这个原因,我们在第一个演示中使用了:hover 伪类。

在CSS动画中,当动画完成后,元素会立即返回到其默认的样式。另一方面,CSS转场默认是双向运行的。

例如,当我们的背景从黑色变为红色时,动画也会运行,反之亦然。要用CSS动画实现这个功能,我们需要再次定义动画,并将animation-direction 属性设置为reverse

多个动画

要使用CSS动画创建多个动画,我们可以在一个@keyframes at-rule中输入所有我们想要动画的属性,并在一个animation 属性中使用它,如下面的代码片断所示。

.element {
  animation: color-change 2s ease-in-out 1s infinite forwards;
}

@keyframes color-width-change {
  0% {
    background: black;
  }
  25% {
    width: 200px;
  }
  100% {
    background: red;
    width: 500px;
  }
}

另一种方法是使用多个@keyframes at-rules,并用逗号分隔动画属性的值。如果你想为动画属性使用不同的值,下面的方法是理想的。

.element {
  animation: color-change 2s ease-in-out 1s infinite forwards, width-change 3s ease-in 0s infinite forwards;
}

@keyframes color-change {
  0% {
    background: black;
  }
  100% {
    background: red;
  }
}

@keyframes width-change {
  25% {
    width: 200px;
  }
  100% {
    width: 500px;
  }
}

下面的CodePen包含了上述代码片断的演示。

参见CodePen上Udoh Idorenyin(@idorenyinudoh)
的Pen
css动画测试2。

你会发现,当color-change 动画完成后,width-change 动画仍在运行。为了避免重复,你可以从速记中排除一些属性,而用单独的animation-* 属性的一个值来指定它们。

网络动画API

JavaScript的动画方法,即Web Animations API,为开发者提供了对CSS动画的更多控制和细微差别。虽然Web Animations API最初在设置时可能看起来比较复杂,但你可以将它与元素的样式分离,使它比CSS的替代方案更容易编写和更直接。

为了用Web Animations API给一个DOM元素制作动画,我们在该元素上调用animate() 方法。animate() 方法有两个参数,关键帧和选项。与CSS过渡和CSS动画一样,该元素必须是可动画的。

关键帧

关键帧可以是一个关键帧对象的数组,也可以是一个以数值数组为属性的对象。

const keyframes = [
    { opacity: 1 },
    { opacity: 0 },
    { opacity: 1 }
]

// OR

const keyframes = {
    opacity: [ 1, 0, 1 ]
}

在第一种方法中,关键帧对象分布在动画周期的偶数点上。例如,在上面的代码块中,这些点默认为百分之零、百分之五十和百分之百。要改变这些点,在关键帧对象中设置一个offset 属性,其值在0.01.0 之间,0.5 是50%。

考虑一下下面这个CSS的例子。

@keyframes fade-in-out {
    0% {
        opacity: 0;
    }
    60% {
        opacity: 1;
    }
    100% {
        opacity: 0;
    }
}

使用Web Animations API中的第一个关键帧方法,上面的CSS代码看起来会是这样。

const keyframes = [
    { opacity: 1 },
    { opacity: 0, offset: 0.6 },
    { opacity: 1 }
]

如果我们使用第二个关键帧方法,并使用一个数组的值作为属性,我们的CSS代码将如下。

const keyframes = {
  opacity: [0, 1, 0],
  offset: [0, 0.6, 1] //could also be [0, 0.6]
}

在CSS中,你可以为一个动画使用一个计时函数,然而,通过Web Animations API,你可以为每个关键帧以及整个动画指定一个计时函数。

为一个关键帧包括easing 属性,与包括offset 属性的方式相同。easing 属性将从该关键帧应用到下一个指定的关键帧。

const keyframes = [
    { opacity: 1, easing: 'ease-in' },
    { opacity: 0, offset: 0.6, easing: 'ease-out' },
    { opacity: 1, easing: 'ease-in-out' }
]

// OR

const keyframes = {
    opacity: [ 1, 0, 1 ],
    offset: [0, 0.6],
    easing: ['ease-in', 'ease-out', 'ease-in-out']
}

为了在整个动画中包括easing 的值,我们将在选项对象中包括它。

options

options 可以是一个以毫秒为单位指定动画持续时间的整数类型,也可以是一个至少包含一个与CSS动画属性等价的EffectTiming 对象。让我们回顾一下Web Animations API的这些属性的等价物。

CSS动画属性Web Anim ations API的等价物
animation-nameid
animation-durationduration
animation-timing-functioneasing
animation-fill-modefill
animation-iteration-countiterations
animation-directiondirection
animation-delaydelay

我们很快就会介绍animation-play-state CSS属性的对等物。然而,有几个属性你可以在options 对象中包含,但没有CSS等价物。

endDelay 指定动画结束后的延迟长度,这在我们希望播放背对背的动画时很有帮助。

iterationStart 指定了一个迭代中动画应该开始的时间点,范围从0.01.0 。例如,0.3 的值意味着动画应该在30%的关键帧点开始。

composite 指定了一个动画的值如何与其他没有composite 属性的动画相结合。例如,add 的值会将下一个动画添加到上一个动画中。当然,前一个动画会被覆盖掉。

iterationComposite 指定了在动画中如何从迭代到迭代建立值。

animate()

animate() 方法返回一个Animation 对象。让我们考虑一下这个对象所提供的属性和方法。

属性

  • currentTime :动画的当前点,单位是毫秒
  • effect:AnimationEffect 对象,它是一个KeyframeEffect 对象
  • finished :返回一个承诺,解决动画结束的问题。
  • id: 用来识别动画的id
  • pending :该动画正在等待一个操作的完成
  • playbackRate :动画的播放速率
  • ready :当动画准备好播放时,返回一个解决的承诺。
  • replaceState :返回动画的替换状态
  • startTime :动画预定开始的时间
  • timeline :与该动画相关的时间线
  • playState :指定动画是否正在播放。

方法

  • cancel() :清除动画创建的KeyframeEffect ,并结束其播放。
  • finish(): 前进到动画的终点
  • pause() :暂停动画播放
  • persist() :当浏览器将动画删除时,将动画保留在该元素上。
  • play() :开始或恢复动画
  • reverse() :从结束到开始播放动画
  • updatePlaybackRate() :在动画开始后设置动画的速度
  • commitStyles() :将动画的结束状态的造型提交给元素

这个对象的其他事件包括cancel,finish, 和remove 事件。

演示

让我们使用Web Animations API的属性、方法和选项重新创建我们前面的动画。我们的JavaScript文件应该看起来像下面的代码块。

const element = document.querySelector('div');

const keyframes = {
    background: [ 'black', 'red' ]
}

const options = {
    id: "color-change",
    duration: 2000,
    delay: 1000,
    easing: "ease-in-out",
    iterations: Infinity,
    fill: "forwards"
}

element.animate(keyframes, options);

为了连续播放动画,我们使用JavaScript关键字Infinity 作为options 对象中iterations 属性的值。

参见CodePen上Udoh Idorenyin(@idorenyinudoh) 的Pen
网络动画api测试

为了创建多个动画,我们可以在一个关键帧对象中包含多个属性。为了在options 对象中使用不同的属性值,我们可以创建多个关键帧和options 对象,在一个元素上多次使用animate() 方法。

请看CodePen上Udoh Idorenyin(@idorenyinudoh)
的Pen
web动画api测试2。

使用WAAPI制作动画的优势

现在我们已经了解了如何使用CSS过渡、CSS动画和Web Animations API来制作动画,让我们注意一下使用Web Animations API的一些经常被忽视的关键优势。

首先,使用CSS,我们只能为整个动画使用一个计时函数。然而,使用Web Animations API,我们可以在options 对象中为不同的关键帧和整个动画指定easing 属性。

Animation 通过Web Animations API,我们可以使用currentTimestartTime 对象的属性以及Animation 事件为一个元素添加多个动画。在CSS中,你必须用另一个动画覆盖一个动画,将所有的动画一起播放,或者用JavaScript给同一个元素添加另一个动画。

网络动画API中options 对象的composite 属性允许我们向浏览器表明我们希望如何在一个元素上运行连续的动画。CSS没有相应的属性。

结论

Web Animations API中的属性、方法和事件使我们很容易在网络上定制动画。根据我的经验,非复杂的动画最好用CSS实现,而更复杂的动画最好用JavaScript实现。

无可否认,从头开始做动画可能会变得非常困难。你可能想考虑像Flow这样的第三方动画工具,它可以将动画导出为Web Animations API这样的格式。

我希望你喜欢这个教程。祝你动画制作愉快

The postThe Web Animations API vs. CSSappeared first onLogRocket Blog.