当前位置:首页 > 文章列表 > 文章 > 前端 > Web Animations API 如何中途反向播放:currentTime、playbackRate 与取消边界

Web Animations API 如何中途反向播放:currentTime、playbackRate 与取消边界

来源:17golang原创 2026-08-26 08:50:52 0浏览 收藏
热门推荐
漫画APP
动画内容聚合,热门资源快捷查看
立即下载

做一个可展开的筛选面板时,最容易遇到的不是“动画怎么写”,而是用户在动画走到一半又点了一次按钮:面板应该顺着当前进度收回,而不是跳到终点再倒放。Web Animations API 把这段播放过程暴露成 Animation 对象,可以读取 currentTime,用 reverse() 改变方向,也能在必要时用 cancel() 清掉效果。

要点速览

  • currentTime 是动画时间轴上的毫秒位置,未开始或没有时间轴时可能是 null
  • 临时改变方向优先调用 reverse();需要固定速度时再用 playbackRate
  • 用户连续点击时不要重新创建 Animation,应复用同一个对象并观察 playState
  • cancel() 会移除动画效果,适合重置,不等同于暂停。

这项能力解决的是“半程切换”

CSS 的 animation-direction 适合声明固定的播放方向,但交互组件常常需要在运行时改变决定:抽屉打开到 40% 时,用户再次点击关闭;提示条刚出现,路由切换要求它立即收起;拖拽结束后还要从当前位置继续播放。

这时把动画保存为变量,比反复调用 element.animate() 更容易维护。保存后的对象同时承担播放控制和状态查询,业务代码可以根据 playState 做按钮禁用、焦点处理和收尾。

Web Animations API 中途反向播放的 currentTime 与 reverse 方向切换示意

最小写法:保存 Animation,再切换方向

下面的例子让一个面板从透明和下移状态进入可见状态。再次点击时不计算剩余时长,直接把当前 Animation 反向播放:

const panel = document.querySelector('.panel');
const toggle = document.querySelector('#toggle');

const motion = panel.animate(
  [
    { opacity: 0, transform: 'translateY(-12px)' },
    { opacity: 1, transform: 'translateY(0)' }
  ],
  { duration: 260, easing: 'ease-out', fill: 'both' }
);

motion.pause();
let opened = false;

toggle.addEventListener('click', () => {
  opened = !opened;
  motion.reverse();
  console.log({ opened, time: motion.currentTime, state: motion.playState });
});

这里第一次调用 reverse() 会把原本的正向播放改为反向,因此更稳妥的实际组件通常会在创建后先把动画暂停并设置到合适的初始位置,再根据 opened 决定调用 play() 还是 reverse()。不要把“方向”误解成“立刻跳到另一端”;它仍然以当前时间位置为基础。

currentTime、playbackRate 和 reverse() 怎么分工

用 currentTime 定位,用 reverse 改方向

currentTime 的单位是毫秒。需要把动画恢复到 120 毫秒处,直接写 motion.currentTime = 120;但读取时要先处理 null,因为尚未关联时间轴或尚未启动的 Animation 没有可用时间。

reverse() 更像“沿当前轨道掉头”。它适合关闭面板、收起菜单这类从任意中间位置反向返回的操作,也比手工计算剩余时间少一个容易出错的分支。

用 playbackRate 表示速度意图

playbackRate = 1 是正常速度,2 会加速,负值会反向。若只是一次方向切换,用 reverse() 更清楚;若产品确实有“慢速预览”或“快速收起”,可以使用 updatePlaybackRate() 让播放位置先同步再改变速度。

motion.updatePlaybackRate(opened ? 1 : -1);
motion.play();

不要把 playbackRate = 0 当成标准暂停状态。它会让时间不再前进,但 playState 不一定变成 paused;需要暂停时调用 pause(),状态判断会更直接。

连续点击时,先看状态再处理收尾

一个常见错误是每次点击都新建动画。这样不仅会叠加多个效果,旧对象还可能在完成后继续影响样式。更简单的做法是保留一个 Animation,并把完成和取消当成两个不同结果:

function setPanel(open) {
  if (open) {
    motion.play();
  } else {
    motion.reverse();
  }

  motion.finished
    .then(() => {
      console.log('finished', motion.playState, motion.currentTime);
    })
    .catch(() => {
      console.log('animation interrupted');
    });
}

如果下一次操作发生在 Promise 完成前,旧的 finished 可能会被取消。把它当作正常的中断分支即可,不要在 catch 里重复创建另一套动画。

Web Animations API cancel 中止动画并恢复初始样式的状态判断链

cancel() 不是暂停:重置与保留进度要分开

pause() 会保留当前位置,之后还能继续播放;cancel() 则会中止播放并移除这个 Animation 造成的效果,startTimecurrentTime 也会回到未激活状态。关闭组件后要彻底回到 CSS 初始状态,才使用 cancel()

如果动画由 CSS 类名控制,重置时还要同步移除打开状态,否则 JavaScript 已经取消效果,CSS 规则仍可能把面板留在可见状态。对于需要保留最终视觉结果的场景,可以在确认结束后再决定是否持久化样式,而不是把 cancel() 当作“提交最终状态”。

和纯 CSS 方案怎么选

静态 hover、页面首次出现和固定的进入/离开效果,CSS 仍然更短,也更容易交给设计同学调整。Web Animations API 的价值在于运行时控制:读取时间、响应连续输入、统一处理完成/取消、动态调整速度。

  • 只有固定方向:优先 CSS transition 或 animation。
  • 需要中途掉头:复用一个 Animation,优先考虑 reverse()
  • 需要按业务事件定位:使用 currentTime,并处理 null
  • 需要彻底撤销效果:使用 cancel(),同时清理组件状态和焦点。

兼容性要求较宽时,可以保留 CSS 类名作为视觉降级;JavaScript 控制逻辑只在确认 Element.prototype.animate 存在后启用。降级版本宁可少一个中途反向效果,也不要因为控制器缺失让面板无法打开。

常见问题

currentTime 为什么是 null?

Animation 尚未开始、没有可用时间轴或已经取消时都可能得到 null。读取前先判断,写入时也不要把 null 当成 0。

reverse() 和设置负 playbackRate 有什么区别?

两者都能改变播放方向,但 reverse() 直接表达“沿当前进度掉头”;负 playbackRate 更适合同时表达速度,代码中应明确处理播放状态。

动画完成后还能 reverse() 吗?

可以,但要留意完成端点和播放状态。组件可以复用同一个 Animation,也可以在需要独立生命周期时重新创建,关键是不要让旧对象和新对象同时作用于同一个元素。

什么时候应该调用 cancel()?

当组件销毁、路由离开或需要恢复 CSS 初始样式时调用。只是暂时停住时使用 pause(),不要丢掉可继续的进度。

把控制面收进一个小状态机

Web Animations API 并不替组件决定业务状态。实际项目里,把“目标状态”与 Animation 的“播放状态”分开记录,再在每次用户操作时复用同一个对象,通常就能解决半程切换、快速重复点击和销毁清理这三类问题。先用 currentTime 验证时间位置,再选择 reverse()pause()cancel(),动画代码会比不断叠加 CSS 类更容易复查。

版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Go os.Root 相对路径校验怎么避免目录逃逸:Open、权限边界与错误判断Go os.Root 相对路径校验怎么避免目录逃逸:Open、权限边界与错误判断
上一篇
Go os.Root 相对路径校验怎么避免目录逃逸:Open、权限边界与错误判断
Go http.ServeContent 为什么 Range 请求会返回 416:Content-Range、Seek 与文件大小核对
下一篇
Go http.ServeContent 为什么 Range 请求会返回 416:Content-Range、Seek 与文件大小核对
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • ljg-skills -
    ljg-skills
    ljg-skills 是李继刚开源的 AI 技能与提示词集合,面向大模型使用者整理了一批可复用的 prompt、角色设定和任务技能模板,适合用于学习提示词设计、搭建个人 AI 工作流和沉淀团队常用智能体能力。
    5280次使用
  • MELO音乐 - AI 音乐生成平台,支持多模态创作能力
    MELO音乐
    MELO音乐是一站式AI视频与音乐制作助手,对标suno, udio的高品质体验。提供伴奏生成、原创写词、无损导出、哼唱识曲、混音变声等全套音频与短视频编辑工具。无论是流行Kpop、电音说唱、民谣古风、摇滚儿歌还是商用轻音乐,MELO为你免费谱曲,轻松做同款!
    4791次使用
  • UniScribe - AI 免费在线音视频转文字平台
    UniScribe
    UniScribe 是一款 AI 音视频转文字与内容整理工具,支持上传音频、视频文件或粘贴 YouTube 链接,自动生成转写文本、摘要、思维导图和关键问题,并支持多格式导出,适合会议记录、课程学习、访谈整理和内容创作复盘。
    4742次使用
  • 剧云 - 免费 AI 智能中文剧本创作平台
    剧云
    剧云是专业中文剧本创作平台,安全稳定运行十余年,集成AI编剧、剧本医生审核、人物小传、剧情关系图、大纲编写、多人协作、Word导入导出、版权管控功能,数据安全防护,轻松高效创作剧本。
    5002次使用
  • 万象有声 - AI 一站式有声内容创作平台
    万象有声
    万象有声,一个专为有声创作者打造的新一代智能有声内容创作平台。平台提供专业的智能拆章、智能画本编辑、AI配音、AI生成音效、后期制作、智能对轨、智能审听等有声创作全流程工具,可以帮助创作者高效、低成本创作出引人入胜的有声作品。立即体验,让有声书制作更简单!
    4944次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码