CSS 动画(CSS Animations)

核心知识点讲解

CSS 动画是 CSS3 中引入的一项强大功能,它允许你创建复杂的动画效果,而无需使用 JavaScript。CSS 动画通过 @keyframes 规则定义动画的关键帧,然后使用动画属性将动画应用到元素上。

基本概念

  • 关键帧(Keyframes):动画中的特定时间点,定义了元素在该时间点的样式
  • 动画属性(Animation Properties):控制动画的持续时间、延迟、重复次数、方向等
  • 动画名称(Animation Name):标识特定的 @keyframes 规则
  • 动画持续时间(Animation Duration):动画完成一个周期所需的时间
  • 动画延迟(Animation Delay):动画开始前的等待时间
  • 动画重复次数(Animation Iteration Count):动画应重复的次数
  • 动画方向(Animation Direction):动画的播放方向
  • 动画填充模式(Animation Fill Mode):定义动画开始前和结束后的元素样式
  • 动画播放状态(Animation Play State):控制动画的播放和暂停

定义关键帧

使用 @keyframes 规则定义动画的关键帧:

@keyframes animation-name {
  from {
    /* 初始样式 */
  }
  to {
    /* 结束样式 */
  }
}

或者使用百分比定义多个关键帧:

@keyframes animation-name {
  0% {
    /* 初始样式 */
  }
  50% {
    /* 中间样式 */
  }
  100% {
    /* 结束样式 */
  }
}

动画属性

1. animation-name

指定要应用的动画名称:

.element {
  animation-name: animation-name;
}

2. animation-duration

指定动画完成一个周期所需的时间:

.element {
  animation-duration: 1s; /* 1秒 */
}

3. animation-timing-function

指定动画的速度曲线:

.element {
  animation-timing-function: ease; /* 默认值,缓入缓出 */
  /* 或 */
  animation-timing-function: linear; /* 匀速 */
  /* 或 */
  animation-timing-function: ease-in; /* 缓入 */
  /* 或 */
  animation-timing-function: ease-out; /* 缓出 */
  /* 或 */
  animation-timing-function: ease-in-out; /* 缓入缓出 */
  /* 或 */
  animation-timing-function: cubic-bezier(n, n, n, n); /* 自定义贝塞尔曲线 */
  /* 或 */
  animation-timing-function: steps(n); /* 步进函数 */
}

4. animation-delay

指定动画开始前的等待时间:

.element {
  animation-delay: 0s; /* 默认值,无延迟 */
  /* 或 */
  animation-delay: 1s; /* 1秒延迟 */
}

5. animation-iteration-count

指定动画应重复的次数:

.element {
  animation-iteration-count: 1; /* 默认值,播放一次 */
  /* 或 */
  animation-iteration-count: 3; /* 播放三次 */
  /* 或 */
  animation-iteration-count: infinite; /* 无限重复 */
}

6. animation-direction

指定动画的播放方向:

.element {
  animation-direction: normal; /* 默认值,正常方向 */
  /* 或 */
  animation-direction: reverse; /* 反向 */
  /* 或 */
  animation-direction: alternate; /* 交替方向,奇数次正常,偶数次反向 */
  /* 或 */
  animation-direction: alternate-reverse; /* 反向交替,奇数次反向,偶数次正常 */
}

7. animation-fill-mode

定义动画开始前和结束后的元素样式:

.element {
  animation-fill-mode: none; /* 默认值,不应用任何样式 */
  /* 或 */
  animation-fill-mode: forwards; /* 保持结束状态的样式 */
  /* 或 */
  animation-fill-mode: backwards; /* 应用开始状态的样式 */
  /* 或 */
  animation-fill-mode: both; /* 同时应用开始和结束状态的样式 */
}

8. animation-play-state

控制动画的播放和暂停:

.element {
  animation-play-state: running; /* 默认值,运行中 */
  /* 或 */
  animation-play-state: paused; /* 暂停 */
}

9. animation

所有动画属性的简写:

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

实用案例分析

案例一:简单的淡入淡出动画

创建一个简单的淡入淡出动画:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>淡入淡出动画</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body {
      font-family: Arial, sans-serif;
      padding: 20px;
      display: flex;
      flex-direction: column;
      align-items: center;
    }

    .box {
      width: 200px;
      height: 200px;
      background-color: #3498db;
      border-radius: 8px;
      display: flex;
      justify-content: center;
      align-items: center;
      color: white;
      font-size: 1.2rem;
      font-weight: bold;
      animation: fade 3s infinite alternate;
    }

    @keyframes fade {
      from {
        opacity: 0.2;
        transform: scale(0.8);
      }
      to {
        opacity: 1;
        transform: scale(1);
      }
    }

    .controls {
      margin-top: 30px;
    }

    .btn {
      padding: 10px 20px;
      margin: 0 10px;
      border: none;
      border-radius: 4px;
      background-color: #3498db;
      color: white;
      cursor: pointer;
      font-size: 1rem;
    }

    .btn:hover {
      background-color: #2980b9;
    }

    .box.paused {
      animation-play-state: paused;
    }
  </style>
</head>
<body>
  <h1>淡入淡出动画示例</h1>
  <div class="box" id="box">淡入淡出动画</div>
  <div class="controls">
    <button class="btn" id="play-btn">播放</button>
    <button class="btn" id="pause-btn">暂停</button>
  </div>
  <script>
    const box = document.getElementById('box');
    const playBtn = document.getElementById('play-btn');
    const pauseBtn = document.getElementById('pause-btn');

    playBtn.addEventListener('click', () => {
      box.classList.remove('paused');
    });

    pauseBtn.addEventListener('click', () => {
      box.classList.add('paused');
    });
  </script>
</body>
</html>

案例二:旋转动画

创建一个旋转动画:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>旋转动画</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body {
      font-family: Arial, sans-serif;
      padding: 20px;
      display: flex;
      flex-direction: column;
      align-items: center;
    }

    .container {
      display: flex;
      gap: 30px;
      margin-top: 30px;
      flex-wrap: wrap;
      justify-content: center;
    }

    .box {
      width: 150px;
      height: 150px;
      border-radius: 8px;
      display: flex;
      justify-content: center;
      align-items: center;
      color: white;
      font-size: 1rem;
      font-weight: bold;
      animation-duration: 3s;
      animation-iteration-count: infinite;
      animation-timing-function: linear;
    }

    .box1 {
      background-color: #e74c3c;
      animation-name: rotate;
    }

    .box2 {
      background-color: #3498db;
      animation-name: rotate-reverse;
    }

    .box3 {
      background-color: #2ecc71;
      animation-name: rotate-3d;
      perspective: 1000px;
    }

    @keyframes rotate {
      from {
        transform: rotate(0deg);
      }
      to {
        transform: rotate(360deg);
      }
    }

    @keyframes rotate-reverse {
      from {
        transform: rotate(360deg);
      }
      to {
        transform: rotate(0deg);
      }
    }

    @keyframes rotate-3d {
      0% {
        transform: rotateX(0deg) rotateY(0deg);
      }
      50% {
        transform: rotateX(180deg) rotateY(180deg);
      }
      100% {
        transform: rotateX(360deg) rotateY(360deg);
      }
    }

    .controls {
      margin-top: 30px;
    }

    .speed-control {
      margin-bottom: 20px;
    }

    label {
      display: block;
      margin-bottom: 10px;
      font-weight: bold;
    }

    input[type="range"] {
      width: 300px;
    }
  </style>
</head>
<body>
  <h1>旋转动画示例</h1>
  <div class="container">
    <div class="box box1">顺时针旋转</div>
    <div class="box box2">逆时针旋转</div>
    <div class="box box3">3D 旋转</div>
  </div>
  <div class="controls">
    <div class="speed-control">
      <label for="speed">动画速度:<span id="speed-value">3</span>s</label>
      <input type="range" id="speed" min="0.5" max="5" step="0.5" value="3">
    </div>
  </div>
  <script>
    const speedControl = document.getElementById('speed');
    const speedValue = document.getElementById('speed-value');
    const boxes = document.querySelectorAll('.box');

    speedControl.addEventListener('input', () => {
      const speed = speedControl.value;
      speedValue.textContent = speed;
      boxes.forEach(box => {
        box.style.animationDuration = `${speed}s`;
      });
    });
  </script>
</body>
</html>

案例三:弹跳动画

创建一个弹跳动画:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>弹跳动画</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body {
      font-family: Arial, sans-serif;
      padding: 20px;
      display: flex;
      flex-direction: column;
      align-items: center;
    }

    .container {
      width: 400px;
      height: 300px;
      border: 2px solid #333;
      border-radius: 8px;
      position: relative;
      margin-top: 30px;
      overflow: hidden;
    }

    .ball {
      width: 50px;
      height: 50px;
      background-color: #e74c3c;
      border-radius: 50%;
      position: absolute;
      bottom: 20px;
      left: 50%;
      transform: translateX(-50%);
      animation: bounce 2s infinite;
    }

    @keyframes bounce {
      0%, 20%, 50%, 80%, 100% {
        transform: translateX(-50%) translateY(0);
      }
      40% {
        transform: translateX(-50%) translateY(-150px);
      }
      60% {
        transform: translateX(-50%) translateY(-75px);
      }
    }

    .controls {
      margin-top: 30px;
    }

    .btn {
      padding: 10px 20px;
      margin: 0 10px;
      border: none;
      border-radius: 4px;
      background-color: #3498db;
      color: white;
      cursor: pointer;
      font-size: 1rem;
    }

    .btn:hover {
      background-color: #2980b9;
    }

    .ball.paused {
      animation-play-state: paused;
    }
  </style>
</head>
<body>
  <h1>弹跳动画示例</h1>
  <div class="container">
    <div class="ball" id="ball"></div>
  </div>
  <div class="controls">
    <button class="btn" id="play-btn">播放</button>
    <button class="btn" id="pause-btn">暂停</button>
  </div>
  <script>
    const ball = document.getElementById('ball');
    const playBtn = document.getElementById('play-btn');
    const pauseBtn = document.getElementById('pause-btn');

    playBtn.addEventListener('click', () => {
      ball.classList.remove('paused');
    });

    pauseBtn.addEventListener('click', () => {
      ball.classList.add('paused');
    });
  </script>
</body>
</html>

案例四:打字机效果

创建一个打字机效果的动画:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>打字机效果</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body {
      font-family: 'Courier New', monospace;
      padding: 20px;
      display: flex;
      flex-direction: column;
      align-items: center;
      background-color: #f4f4f4;
    }

    .typewriter {
      max-width: 600px;
      margin: 30px 0;
      padding: 20px;
      background-color: white;
      border-radius: 8px;
      box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
    }

    .typewriter-text {
      font-size: 1.2rem;
      line-height: 1.6;
      white-space: nowrap;
      overflow: hidden;
      border-right: 3px solid #3498db;
      animation: typing 4s steps(40, end), blink-caret 0.75s step-end infinite;
    }

    @keyframes typing {
      from {
        width: 0;
      }
      to {
        width: 100%;
      }
    }

    @keyframes blink-caret {
      from, to {
        border-color: transparent;
      }
      50% {
        border-color: #3498db;
      }
    }

    .controls {
      margin-top: 20px;
    }

    .btn {
      padding: 10px 20px;
      margin: 0 10px;
      border: none;
      border-radius: 4px;
      background-color: #3498db;
      color: white;
      cursor: pointer;
      font-size: 1rem;
    }

    .btn:hover {
      background-color: #2980b9;
    }

    .typewriter.paused .typewriter-text {
      animation-play-state: paused;
    }
  </style>
</head>
<body>
  <h1>打字机效果示例</h1>
  <div class="typewriter" id="typewriter">
    <p class="typewriter-text">这是一个打字机效果的动画示例。通过 CSS 动画,我们可以模拟打字机逐字输入的效果,同时添加光标闪烁的动画,使效果更加逼真。</p>
  </div>
  <div class="controls">
    <button class="btn" id="play-btn">播放</button>
    <button class="btn" id="pause-btn">暂停</button>
    <button class="btn" id="restart-btn">重新开始</button>
  </div>
  <script>
    const typewriter = document.getElementById('typewriter');
    const playBtn = document.getElementById('play-btn');
    const pauseBtn = document.getElementById('pause-btn');
    const restartBtn = document.getElementById('restart-btn');

    playBtn.addEventListener('click', () => {
      typewriter.classList.remove('paused');
    });

    pauseBtn.addEventListener('click', () => {
      typewriter.classList.add('paused');
    });

    restartBtn.addEventListener('click', () => {
      typewriter.classList.add('paused');
      setTimeout(() => {
        typewriter.classList.remove('paused');
      }, 100);
    });
  </script>
</body>
</html>

总结

CSS 动画是一种强大的技术,它具有以下优势:

  1. 无需 JavaScript:可以创建复杂的动画效果,而无需使用 JavaScript
  2. 高性能:CSS 动画由浏览器的渲染引擎处理,通常比 JavaScript 动画性能更好
  3. 灵活的关键帧定义:可以使用 @keyframes 规则定义详细的动画序列
  4. 丰富的动画属性:提供了多种属性来控制动画的各个方面
  5. 易于实现:语法简单直观,易于学习和使用

CSS 动画的应用场景非常广泛,包括:

  • 页面加载动画
  • 元素的进入和退出动画
  • 交互反馈动画
  • 数据可视化动画
  • 游戏和娱乐效果
  • 品牌展示和营销效果

通过掌握 CSS 动画,你可以创建更加生动、吸引人的网页效果,提高用户体验和网站的视觉吸引力。

« 上一篇 Flexbox 布局 下一篇 » CSS 过渡效果(CSS Transitions)