使用requestAnimationFrame替代setInterval时函数未触发问题求助
解决requestAnimationFrame未按预期工作的问题
我看了你的代码,其实requestAnimationFrame是被调用了,但它的执行频率(每秒约60次)完全不符合你CSS动画的节奏,导致按钮切换得太快,动画还没来得及展示就被切换走了,所以看起来像是没生效。
问题根源
你的CSS动画zoominout时长是1秒,但requestAnimationFrame会每16ms左右执行一次btnBlinkRun,这意味着index会在1秒内切换几十次,动画刚启动就被移除了ID,自然看不到效果。而且你的场景是间隔固定时间切换元素执行动画,用requestAnimationFrame逐帧循环完全没必要,反而会浪费性能。
正确解决方案
我们应该在当前元素的动画结束后再切换到下一个元素,利用animationend事件来触发下一次循环,这样既符合动画节奏,又能保证性能。修改后的代码如下:
HTML
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div> <div class="btn" id="ani--scaleinout"></div> <div class="btn"></div> <div class="btn"></div> </div>
CSS
.btn{ width: 30px; height: 30px; background: blue; border-radius: 100%; margin-bottom: 10px; } #ani--scaleinout { animation: zoominout 1s ease-in; } @keyframes zoominout { 50% { transform: scale(1.4); } 100% { transform: scale(1); } }
JavaScript
var index = 0; var $btn = $('.btn'); function btnBlinkRun() { // 移除所有元素的动画ID $('#ani--scaleinout').removeAttr('id'); // 给当前元素添加动画ID $($btn[index]).attr('id', 'ani--scaleinout'); // 监听当前元素的动画结束事件(用one避免重复绑定) $($btn[index]).one('animationend', function() { // 更新index,循环切换所有按钮 index = (index + 1) % $btn.length; // 执行下一次动画 btnBlinkRun(); }); } // 启动第一次动画 btnBlinkRun();
补充:如果一定要用requestAnimationFrame
要是你坚持想用requestAnimationFrame来实现(比如需要更精细的时间控制),可以利用它的时间戳参数来控制切换间隔,确保每1秒才切换一次:
var index = 0; var $btn = $('.btn'); var lastTime = 0; const SWITCH_INTERVAL = 1000; // 1秒切换间隔 function btnBlinkRun(timestamp) { // 计算时间差,达到设定间隔才执行切换逻辑 if (!lastTime || timestamp - lastTime >= SWITCH_INTERVAL) { lastTime = timestamp; $('#ani--scaleinout').removeAttr('id'); $($btn[index]).attr('id', 'ani--scaleinout'); index = (index + 1) % $btn.length; } // 继续循环调用 window.requestAnimationFrame(btnBlinkRun); } btnBlinkRun();
这种方式既保留了requestAnimationFrame的性能优势(浏览器空闲时执行,避免掉帧),又能贴合你动画的节奏。
内容的提问来源于stack exchange,提问作者forethought
相关产品推荐
相关产品推荐

