CSS3 animation 动画用法介绍

6,550 阅读7分钟

一、animationtransition 比较

  • transition只能定义开始状态和结束状态,不能定义中间状态,也就是说只有两个状态。而动画可以是多个状态 间的变化。

  • 动画还有一点不同,它可以自动开始。过渡一般需要通过添加样式类或更改状态(如悬停)来触发,但动画可以在页面加载时自动启动。

  • animation更加复杂一些,它允许你按照实际需求添加很多的keyframes来创建动画。它可以自动触发,并且可以循环。

Transitions: A to B

Animations: A to B to C

二、animation 语法介绍

  • 给元素添加animation和添加transition类似。不过它还需要keyframes。并且animation拥有一些transition没有的属性。

  • transition需要指定一个目标属性,例如backgroundallanimation则需要带keyframes的名字来描述动画。

.element {
 animation: ...
}

@keyframes animation-name {
 /* Keyframes go here */
}

单独定义keyframes的好处是我们可以复用这些动画。

2.1、基本属性语法介绍

属性 介绍
animation-name 需要带keyframes的名字来描述动画。
animation-duration 元素动画过程持续时间。例如,1s
animation-timing-function 元素动画时的速率函数。例如, linearease-insteps动画分段函数或自定义的 cubic-bezier 函数)。
animation-delay 元素动画延迟的时间。例如,300ms
animation-direction 设置动画播放方向。normal,reverse,alternate,alternate-reverse
animation-iteration-count 这是动画播放的次数。默认情况下,它将播放一次。也可以指定一个数字,或指定 infinite 以使其永久循环。
animation-fill-mode 默认情况下,动画播放完成元素返回其正常状态。使用 animation-fill-mode,我们可以定义元素在动画结束或开始前的状态。
animation-play-state 暂停或恢复动画。值为runningpaused,默认为running。可以使用 JavaScript设置此值,控制动画播放状态。

2.2、keyframes介绍

keyframes 是用来描述动画过程中一系列变化的。

在网页上有一个div 标签,它的背景颜色不断地在变,像下面图中显示的那样:

我们可以用百分比来描述上面的动画:0%的时候蓝色背景,50%的时候橙色,100%的时候绿色

0% Blue
50% Green
100% Orange

将这些百分比按照keyframes的规则去写并命名。 结果如下:

@keyframes change-background {
  0% {
    background: blue;
  }
  50% {
    background: green;
  }

  100% {
    background: orange;
  }
}

这个动画名字叫 change-background,我们定义开始、中间和结束时的颜色,在这些状态之间变化时,浏览器会自动去计算颜色值的插值。如下图:

下面是一个简写方式,只有两个状态,初始状态和终止状态,与0%100%的写法是等价的。

@keyframes name {
  from {
    ...
  }
  to {
    ...
  }
}

在一行内写好几个百分比数值,这类似一个暂停的效果。下面的 0%, 20% 的意思是,在0% 的时候,元素的 opacity 的值为0,然后保持这个“状态”直到 20%,然后 opacity 开始改变,并在 100% 的时候变为1:

@keyframes name {
  0%, 20% {
    opacity: 0;
  }
  100% {
    opacity: 1;
  }
}

2.3、animation-name属性介绍

animation-name 指的是动画使用的keyframes的名字。例如:

div {
  animation: foo 3s linear 1s;
}
@keyframes foo {
  ...
}

2.4、animation-duration属性介绍

完成一个动画所需的时间。类似于transition-duration ,以秒或毫秒计,如1s200ms

2.5、animation-timing-function属性介绍

这个属性与transition过渡中定时函数属性的值用法基本相同,但效果上会略有不同。在 transition里时间函数(例如ease-out)是作用于整个transition,但animation 里是作用于关键帧之间:

@keyframes foo {
  0%{
    / *动画开始时变化速度很快,然后按照ease-out的时间函数,到50%之前越来越慢* /
  }
  50%{
    / *然后又开始的时候很快,然后慢慢减速至100%的时候* /
  }
  100%{
    / * 结束 * /
  }
}

所以,timing-function 是用在每一个的keyframe,并不是整个的 keyframes。通常在创建关键帧动画时,选择linear会比较好一些,用使用 keyframes控制动画的节奏。我们可以将动画的计时功能定义为 linear,然后在每个关键帧的上控制速度,比较更细粒度的来控制动画:

@keyframes my-animation {
  0%{
  ...
    animation-timing-function: linear;
  }
  50%{
  ...
    animation-timing-function: ease-out;
  }
}

在这种情况下,动画的前半部分将是线性的,而后半部分将使用ease-out功能。

2.6、animation-delay属性介绍

animation-delaytransition-delay 类似,此属性表示在开始之前动画的等待时间。如果定义的动画是不断循环的,只有第一次循环前会有等待时间。

animation-delay可以给这个属性一个负值,比如-3s。动画会直接从第3s开始执行,仿佛已经运行过了 3s 一样。比如下面这段CSS

.box1,.box2 {
  width: 300px;
  height: 100px;
  outline: 2px dashed #000;
  animation: change-translateX 6s linear;
}
.box {
  animation-delay: -3s;
}

@keyframes change-translateX {
  0% {
    transform: translateX(0px);
  }
  50% {
    transform: translateX(300px);
  }
  100% {
    transform: translateX(600px);
  }
}

上图设置了6s执行完动画,到0%50%的时候执行了3s,所以当动画延迟3s执行的时候,刚好到transform: translateX(300px)这个阶段。最后3s执行50%100%的阶段。加上animation-delay: -3s刚好6s

2.7、animation-direction属性介绍

动画通常从0% 开始,到100%结束。animation-direction使用normalreversealternatealternate-reverse来控制动画变化的方向。

animation-direction四个值的介绍:

  1. normal:按顺序播放,也是默认值。 是指从 0% 开始,到 100% 结束。
  2. reverse:按反方向播放,是指从 100% 播放(或循环)到 0%
  3. alternate:动画轮流反复播放,即从 0% 播放到 100% 然后再播放到 0%
  4. alternate-reverse:指动画轮流反方向反复播放,即从 100% 播放到 0% 然后再播放到 100%。

2.8、animation-iteration-count属性介绍

动画播放的次数。默认情况下,它将播放一次。也可以指定一个数字,或指定 infinite 以使其永久循环。

2.9、animation-fill-mode属性介绍

animation-fill-mode 使用none,forwardsbackwardsboth定义元素在动画结束或开始前的状态。animation-fill-mode四个值的介绍:

  1. none:动画播放完成元素返回其正常状态,也是默认值。
  2. forwards:表示当动画完成后,元素状态保持最后一个关键帧的值。
  3. backwards:有动画延迟时,动画开始前,元素状态保持为第一帧的状态。
  4. both:表示forwardsforwards效果都有。

div {
  animation: change-translateX 4s linear 1s;
}
@keyframes change-translateX {
  0% {
    transform: translateX(300px);
  }

  50% {
    transform: translateX(500px);
  }

  100% {
    transform: translateX(700px);
  }
}

上图设置元素动画keyframes。当animation-fill-modeforwards的时候,元素的状态就保持在了最后一个关键帧的值,也就是transform:translateX(700px)

animation-fill-mode属性为backwards的时候,设置动画延迟3s后执行,可以看到动画在开始前是处于transform: translateX(300px)处,动画结束后回到0px 处。

animation-fill-mode属性为both的时候就包含了forwardsforwards的双重效果。

2.10、animation-play-state属性介绍

如果需要暂停或恢复动画,则可以使用此属性执行操作。值为runningpaused,默认为 running。可以使用JavaScript设置此值,控制动画播放状态。

div:hover {
  animation-play-state: paused;
}

2.11、animation 动画的简写形式

  • 如果提供多组属性值,以逗号进行分隔。
  • 如果只提供一个time参数,则为animation-duration的值定义。
  • 如果提供二个time参数,则第一个为animation-duration的值定义,第二个为animation-delay的值定义。
div {
  animation-name: foo;
  animation-duration: 3s;
  animation-timing-function: linear;
  animation-delay: 1s;
  animation-iteration-count: infinite;
  animation-direction: reverse;
  animation-fill-mode: forwards;
  animation-play-state: pause;
}
    
div {
  animation: foo 3s liner 1s infinite reverse forwards pause;
}

三、摇摆按钮实现

button {
  font-size: 20px;
  padding: 10px 20px;
  background: #3C3C3C;
  color: #fff;
  border-top: 3px solid orange;
  border-radius: 0 0 5px 5px;
}

@keyframes wiggle {
  0%,
  7% {
    transform: rotateZ(0);
  }

  15% {
    transform: rotateZ(-15deg);
  }

  20% {
    transform: rotateZ(10deg);
  }

  25% {
    transform: rotateZ(-10deg);
  }

  30% {
    transform: rotateZ(6deg);
  }

  35% {
    transform: rotateZ(-4deg);
  }

  40%,
  100% {
    transform: rotateZ(0);
  }
}
</style>

具体旋转和变化的可以看下面的动图,浏览器自动完成了每个关键帧之间的插值。

四、loading动画实现

.load {
  display: inline-block;
  width: 200px;
  height: 200px;
  background: orange;
  border-radius: 50%;
  animation: loading 1s linear infinite;
}
.two {
  animation-delay: -0.2s;
}
.three {
  animation-delay: -0.4s;
}
@keyframes loading {
  0% {
    transform: scale(0.3);
    opacity: 0.5;
  }

  50% {
    transform: scale(1);
    opacity: 1;
  }

  100% {
    transform: scale(0.3);
    opacity: 0.5;
  }
}
<div class="load"></div>
<div class="load two"></div>
<div class="load three"></div>

loading动画效果主要是利用animation-delay负值的时间差来实现元素同一时间执行动画而元素样式却不一样。

五、参考

cssanimation.rocks/twitter-fav…

cssanimation.rocks/pseudo-elem…

pc-koubou.jp/magazine/25…

h-wakanda.github.io/css-animati…

css-tricks.com/almanac/pro…

juejin.cn/post/684490…

aotu.io/notes/2016/…