未捕获的类型错误:无法在“窗口”上执行“requestAnimationFrame”:作为参数 1 提供的回调不是函数

Posted

技术标签:

【中文标题】未捕获的类型错误:无法在“窗口”上执行“requestAnimationFrame”:作为参数 1 提供的回调不是函数【英文标题】:Uncaught TypeError: Failed to execute 'requestAnimationFrame' on 'Window': The callback provided as parameter 1 is not a function 【发布时间】:2020-12-22 18:45:03 【问题描述】:

我不太确定我在这里使用 requestAnimationFrame 出了什么问题,因为它似乎可以正常工作,但它抛出了这个错误。

未捕获的 TypeError:无法在“窗口”上执行“requestAnimationFrame”:作为参数 1 提供的回调不是函数。

我正在尝试每 3000 毫秒将一个元素旋转 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>

另外,如果有人可以提出更好的方法(包括在整个事情完成后循环重新开始,那将不胜感激!)

【问题讨论】:

【参考方案1】:

不,它不起作用 - 你自己调用一次rotate_by_90(立即,不是在动画帧准备好时!)并将其返回值(undefined)传递给requestAnimationFrame。相反,你必须传递一个function 转换成requestAnimationFrame,浏览器会调用它。

你也可以传递一个匿名函数,所以你的代码可以通过像这样添加() =&gt;来修复:

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($degreesdeg)`)
  

  // 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。)

【讨论】:

requestAnimationFrame(rotate_by_90.bind(this, degrees, iteration)) 也可以。 是的,但阅读和理解起来不太直观。 非常感谢,这真的很有帮助,我现在不得不进一步调整以添加更多动画,但会以您的建议为起点,再次感谢!

以上是关于未捕获的类型错误:无法在“窗口”上执行“requestAnimationFrame”:作为参数 1 提供的回调不是函数的主要内容,如果未能解决你的问题,请参考以下文章

未捕获的类型错误:无法读取未定义的属性“toLowerCase”

未捕获的类型错误:无法读取未定义的属性“createDocumentFragment”

错误未捕获类型错误:无法读取完整日历上未定义的属性“hasTime”

未捕获的类型错误:无法读取文本字段上未定义错误的属性“toLowerCase”

未捕获的安全错误:无法在“历史记录”上执行“replaceState”:无法在原始“null”的文档中创建

未捕获的类型错误:无法使用“in”运算符在