【知识梳理】CSS中的动画三剑客

599 阅读5分钟

写在前面


  梳理一下使用 CSS 书写动画的方法,便于后面业务中使用。

为什么要写动画


  1. 增加过渡,减少突兀的变化(变化的连续性)
  2. 效果炫酷,吸引眼球(视觉的吸引性)
  3. 传递更多的信息

一、Transition


  过渡,针对的是同一个元素在多个状态之间变化的渐进性

  它可以为一个元素在不同状态之间切换的时候定义不同的过渡效果(有点类似 PPT 的转场)。比如在不同的伪类之间切换,像是 :hover:active或者通过 JS 实现的状态变化。

transition 属性可以被指定为一个或多个 CSS 属性的过渡效果,多个属性之间用逗号进行分隔。

<!DOCTYPE html>
<html>
  <head>
    <title>过渡</title>
    <style>
      .rectangle {
        width: 100px;
        height: 100px;
        transition: all 2s;
        // transition: width 2s, height 3s;
      }
      .rectangle:hover {
        width: 250px;
        height: 250px;
      }
    </style>
  </head>
  <body>
    <div class="rectangle">
      我是矩形
    </div>
  </body>
</html>

transiton 是4个属性的简写:transition-property, transition-duration, transition-timing-function, transition-delay。

它的特点是:

  1. 针对同一个元素的不同状态。
  2. 隐式过渡,开始和结束之间的状态是由浏览器决定的。

Vue中 的 transition

<template>
  <div class="wrap">
    <div>它是标题</div>
    <transition name="fade">
      <div v-if="isShow"></div>
    </transition>
  </div>
</template>

  在 Vue 中,框架本身提供了 <transition>标签来包裹 v-if/v-show 的元素,使用 name 属性定位这个过渡标签。Vue 针对自定义的 name 属性值,提供了一些 css 自定义类名。实际的过渡样式是写在这些钩子类名中的。

  需要弄清楚的是 Vue 中的过渡实际上是包含了两个状态:元素插入和元素删除。

  当插入或删除包含在transition组件中的元素时,Vue 将会做以下处理:

  1. 自动嗅探目标元素是否应用了 CSS 过渡或动画,如果是,在恰当的时机添加/删除 CSS 类名。
  2. 如果过渡组件提供了 JavaScript 钩子函数,这些钩子函数将在恰当的时机被调用。
  3. 如果没有找到 JavaScript 钩子并且也没有检测到 CSS 过渡/动画,DOM 操作(插入/删除)在下一帧中立即执行。(注意:这里指浏览器逐帧动画机制,和 Vue 的 nextTick概念不同)。

二、Transform


  CSStransform属性允许你旋转(rotate),缩放(scale),倾斜(skew)或平移(translate)给定元素。这是通过修改 CSS 视觉格式化模型的坐标空间来实现的。

⚠️注意:transform 只能转换由盒模型定位的元素。也就是说,具有 display: block; 的元素。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .box {
      width: 150px;
      height: 50px;
      background: red;
      transition: transform 2s;
    }
    .box:hover {
      transform: translate(100px, 200px) rotate(0.25turn);
    }
  </style>
</head>
<body>
  <div class="wrap">
    <div class="box">这是盒子</div>
  </div>
</body>
</html>

三、Animation


  Animation是名副其实的动画了,相对于前面说的 transform 只能对给定元素做4个大的方面的变换,它能做的更多更多。Animation使得可以将从一个 CSS 样式配置转换到另一个 CSS 样式配置。其中不同的样式配置是对开发者没有限制的。它是基于关键帧的概念来描述动画的,就好像久远之前学习的 flash 动画一样,开发者需要定义整个动画过程中不同的帧。最后不同的帧组合在一起形成了我们想要的动画。

  基于此,Animation包括两个部分:描述动画的样式规则用于指定动画开始、结束以及中间点样式的关键帧。第一部分描述动画的样式规则,换句话说就是配置动画。这个需要使用CSS属性:animation和其子属性。这个属性允许配置动画时间、时长以及其他动画细节,但是该属性不能配置动画的实际表现。动画的实际表现是由 @keyframes规则实现,也就是关键帧。

配置动画时间等

  animation是8个属性的简写:

  1. animation-name

    指定由 @keyframes描述的关键帧名称

  2. animation-duration

    设置动画一个周期的时长

  3. animation-timing-function

    设置动画速度,即通过建立加速度曲线,设置动画在关键帧之间是如何变化

  4. animation-delay

    设置延时,即从元素加载完成之后到动画序列开始执行的这段时间

  5. animation-iteration-count

    设置动画重复次数,可以指定 infinite 无限次重复动画

  6. animation-direction

    设置动画在每次运行完后是反向运行还是重新回到开始位置重复运行

  7. animation-fill-mode

    指定动画执行前后如何为目标元素应用样式

  8. animation-play-state

    允许暂停和恢复健康动画

定义动画的关键帧

  一旦完成动画的时间等配置,接下来就需要定义动画的表现。通过使用 @keyframes建立两个或两个以上关键帧来实现。每一个关键帧都描述了动画元素在给定的时间点上应该如何渲染。

  因为动画的时间设置是通过 CSS 样式定义的,关键帧使用百分比来指定动画发生的时间点。换句话说,关键帧的定义需要依托整个动画的执行时间,通过一些方式定位到不同的时间点,从而应用不同的 CSS 样式。0%表示动画的第一时刻,100%表示动画的最终时刻。因为这两个时间点十分重要,所以还有特殊的别名:fromto。这两个都是可选的,若from/0%to/100%未指定,则浏览器使用计算值开始或结束动画。

  当然,也可以包含额外可选的关键帧,描述动画开始和结束之间的状态。

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .circle {
      width: 150px;
      height: 150px;
      background: #1a66a6;
      border: 5px solid black;
      border-radius: 50%;
      animation: translate 3s ease-in 1s infinite reverse;
    }
    @keyframes translate {
      form {
        margin-left: 0;
      }
​
      75% {
        margin-left: 120px;
        background: yellow;
      }
​
      to {
        margin-left: 300px;
      }
    }
​
  </style>
</head>
<body>
  <div class="wrap">
    <div class="circle"></div>
  </div>
</body>
</html>

translate.gif

参考文章


  1. 使用 CSS transitions—MDN
  2. Vue文档—进入离开&列表过渡
  3. 使用transform—MDN
  4. 使用CSS动画—MDN
  5. animation—MDN