问题描述
我不太确定我在这里使用requestAnimationFrame会出什么问题,因为它似乎可以正常工作,但是会引发此错误。
未捕获的TypeError:无法在“窗口”上执行“ requestAnimationFrame”:作为参数1提供的回调不是函数。
我试图每3000ms将一个元素旋转90度,然后淡入/淡出其他一些元素。这可能不是最优雅的方法,我怀疑不是,我对JS的理解很基础。因此,如果有人能解释造成此错误的原因,我将非常感谢。
var iteration = 0,degrees = 0;
function rotate_by_90(degrees,iteration) {
if(iteration <= 3) {
var deg = degrees - 90,new_deg = deg;
setTimeout(function() {
$('#rotate').css('transform','translateZ(-60px) rotateX(' + deg + 'deg');
console.log(new_deg + ' degrees');
iteration++;
console.log(iteration + ' iteration');
requestAnimationFrame(rotate_by_90(new_deg,iteration));
},3000);
} else {
$('#rotating_text').fadeOut();
$('#animation_overlay').fadeIn();
}
};
requestAnimationFrame(rotate_by_90(degrees,iteration));
HTML
<div id="rotating_text" class="rotating_text">
<span>Some text </span>
<div class="rotate_container">
<div id="rotate" class="rotate">
<span>thing 1</span>
<span>thing 2</span>
<span>thing 3</span>
<span>thing 4</span>
</div>
</div>
</div>
<div id="animation_overlay" class="animation_overlay">
<span>Some stuff</span>
</div>
此外,如果有人可以建议一种更好的方法(包括在整个过程完成后循环循环以再次开始,那将非常感激!)
解决方法
不,它不起作用-您自己一次调用rotate_by_90
(立即,当动画帧准备好时就没有!),并将其返回值(undefined
)传递到requestAnimationFrame
中。 ,您必须将 function 传递到requestAnimationFrame
中,浏览器会为您调用。
您也可以传递匿名函数,因此只需添加() =>
即可固定代码,
requestAnimationFrame(() => rotate_by_90(degrees,iteration));
关于总体上如何更好地执行此操作,我建议使用异步函数和实际循环:
// First,get some promisified versions of setTimeout and requestAnimationFrame:
const delay = ms => new Promise(resolve => setTimeout(resolve,ms))
const waitForAnimationFrame = () => new Promise(resolve => requestAnimationFrame(resolve))
// Next,our main function:
async function rotationAnimation () {
let degrees = 0
// Loop from 0 to 3
for (let iteration = 0; iteration <= 3; iteration++) {
// Update degrees
degrees -= 90
// Wait 3 seconds + animation frame
await delay(3000)
await waitForAnimationFrame()
// Log variables
console.log(`Iteration ${iteration},${degrees} degrees`)
// Update the CSS
$('#rotate').css('transform',`translateZ(-60px) rotate(${degrees}deg)`)
}
// After the loop is done,crossfade the elements
$('#rotating_text').fadeOut()
$('#animation_overlay').fadeIn()
}
// Call our main function,and handle rejections:
rotationAnimation().catch(e => console.error('Error during animation:',e))
.rotate {
width: 60px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="rotating_text" class="rotating_text">
<span>Some text </span>
<div class="rotate_container">
<div id="rotate" class="rotate">
<span>thing 1</span>
<span>thing 2</span>
<span>thing 3</span>
<span>thing 4</span>
</div>
</div>
</div>
<div id="animation_overlay" class="animation_overlay">
<span>Some stuff</span>
</div>
注意:我保留了分别计算迭代次数的原始逻辑,从0°开始,但是在第一次更新该元素之前立即减小到-90°。但是,我将rotateX
更改为rotate
,因为否则,示例中-90°/ -270°状态是不可见的,因为您正在查看文本的零宽度“边缘”。
(顺便说一句,您也可以只使用CSS动画来完成全部操作,而无需使用任何JavaScript。)