如何在Rive中实现输入值变化时从当前帧播放动画N秒?
解决输入触发动画从当前帧平滑播放N秒的问题
核心思路
别再用scrub的跳帧逻辑了,换成时间驱动的平滑播放控制——输入变化时记好当前时间,算好要播到什么时候,跟着浏览器刷新帧一步步推进动画,直到凑够N秒,这样就不会卡顿。
具体操作步骤
- 给输入控件绑
input事件(要实时响应就用这个,要是只需要输入完再触发就用change) - 事件触发时,先把之前的播放循环清掉,避免冲突
- 记录当前的精确时间戳,再算出播放结束的时间戳(当前时间 + N*1000)
- 启动
requestAnimationFrame循环:- 每帧算一下已经播了多久
- 没到N秒的话,就按已播时长算出动画该走到哪个进度,平滑更新
- 到点了就停掉循环,暂停动画
示例代码(Web Animations API版)
// 假设你已经有了动画实例和输入控件 const targetAnim = document.getElementById('animated-element').animate( [{ transform: 'scale(1)' }, { transform: 'scale(1.5)' }], { duration: 3000, iterations: Infinity, paused: true } ); const inputCtrl = document.getElementById('value-input'); let playId = null; const playSeconds = 2; // 这里设置你要的N秒 inputCtrl.addEventListener('input', () => { // 先终止之前的播放 if (playId) cancelAnimationFrame(playId); const start = performance.now(); const end = start + playSeconds * 1000; const runPlay = () => { const now = performance.now(); const elapsed = now - start; if (elapsed < playSeconds * 1000) { // 按已流逝时间更新动画进度,不是跳帧 targetAnim.currentTime += (elapsed / 1000) * targetAnim.effect.getTiming().duration; playId = requestAnimationFrame(runPlay); } else { targetAnim.pause(); } }; runPlay(); });
避坑提示
- 用
performance.now()比Date.now()精度高,时间计算更准,减少跳帧概率 - 每次输入都要清掉之前的循环,不然多个循环叠在一起会乱
- 别直接设置
currentTime跳帧,而是基于时间差累加,保证每帧的平滑过渡
内容的提问来源于stack exchange,提问作者elVengador
相关产品推荐
相关产品推荐

