学习目标

  • 掌握 animation-play-stateanimation-fill-mode 属性的语法与取值
  • 实现动画的暂停/播放控制及状态保持效果
  • 学会监听 animationstart/animationend 等动画事件并处理回调逻辑

概念讲解

CSS 动画控制是指通过属性和事件对动画的播放过程进行干预,包括暂停/继续播放、控制动画结束后的状态,以及捕获动画生命周期中的关键节点(开始、结束、重复)。这使得动画不再是独立运行的效果,而是可以与用户交互或其他页面逻辑联动的动态行为。

核心控制维度

  1. 播放状态:控制动画的运行/暂停状态切换
  2. 状态保持:定义动画结束后元素是否保留关键帧中的最终状态
  3. 事件监听:捕获动画开始、结束、重复等关键时刻,触发自定义逻辑

语法参考

1. 动画控制属性

属性名 取值范围 描述
animation-play-state running paused
animation-fill-mode none forwards

2. 动画事件

事件名 触发时机 应用场景
animationstart 动画开始时触发(仅一次) 初始化动画相关数据
animationend 动画完成所有循环后触发 执行动画结束后的回调(如隐藏元素)
animationiteration 每次循环结束时触发(不含最后一次) 实现循环计数、进度更新等逻辑

实战示例

示例1:基础动画控制(播放/暂停)

<div class="box"></div>
<button id="toggleBtn">暂停动画</button>

<style>
.box {
  width: 100px;
  height: 100px;
  background: #4CAF50;
  animation: move 2s linear infinite alternate;
}

/* 定义关键帧动画 */
@keyframes move {
  0% { transform: translateX(0); }
  100% { transform: translateX(300px); }
}
</style>

<script>
const box = document.querySelector('.box');
const toggleBtn = document.getElementById('toggleBtn');
let isPaused = false;

toggleBtn.addEventListener('click', () => {
  isPaused = !isPaused;
  // 控制动画播放状态
  box.style.animationPlayState = isPaused ? 'paused' : 'running';
  toggleBtn.textContent = isPaused ? '继续动画' : '暂停动画';
});
</script>

效果说明:点击按钮可切换动画的播放/暂停状态,动画会在当前位置停止或继续运行。

示例2:动画状态保持与事件监听

<div class="ball"></div>
<p id="status">动画未开始</p>

<style>
.ball {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  background: #ff6b6b;
  /* 动画结束后保持最后一帧状态 */
  animation: bounce 1s ease forwards;
  animation-delay: 1s; /* 延迟1秒开始 */
}

@keyframes bounce {
  0% { transform: translateY(0); opacity: 0; }
  60% { transform: translateY(200px); opacity: 1; }
  100% { transform: translateY(180px); } /* 结束位置 */
}
</style>

<script>
const ball = document.querySelector('.ball');
const statusText = document.getElementById('status');

// 监听动画开始事件
ball.addEventListener('animationstart', () => {
  statusText.textContent = '动画开始!';
});

// 监听动画结束事件
ball.addEventListener('animationend', () => {
  statusText.textContent = '动画结束,已保持最终状态';
  // 3秒后添加新样式
  setTimeout(() => {
    ball.style.boxShadow = '0 5px 15px rgba(0,0,0,0.3)';
  }, 1000);
});
</script>

效果说明:小球从顶部下落并反弹至最终位置后停止,动画结束后触发事件,更新状态文本并添加阴影效果。

注意事项

  • 浏览器兼容性animation-fill-mode 在 IE11 中部分支持,animationend 事件需添加 -webkit- 前缀(如 webkitAnimationEnd)以兼容 Safari 旧版本。
  • 性能优化:避免在动画中修改 width/height 等触发重排的属性,优先使用 transformopacity
  • 事件冒泡:动画事件不会冒泡,需直接绑定在动画元素上;若使用事件委托,需确保目标元素正在执行动画。
  • animation-play-state 继承:子元素不会继承父元素的 animation-play-state,需单独设置。

自测题

  1. 如何让动画在结束后保持第一帧的状态? A. animation-fill-mode: forwards B. animation-fill-mode: backwards C. animation-fill-mode: both D. animation-play-state: paused
  2. 下列哪个事件会在动画每次循环结束时触发(不含最后一次循环)? A. animationstart B. animationend C. animationiteration D. animationcancel
  3. 代码题:实现一个按钮控制的心跳动画,点击按钮暂停时保持当前缩放状态,继续时从暂停位置恢复。 (提示:使用 @keyframes 定义缩放动画,通过 animation-play-state 控制状态)

答案:1.B 2.C 3.(见下方参考代码)

参考代码

.heart {
  width: 100px;
  height: 100px;
  background: red;
  animation: beat 1s infinite alternate;
}
@keyframes beat {
  0% { transform: scale(1); }
  100% { transform: scale(1.5); }
}

(JavaScript 部分参考示例1的播放/暂停逻辑)