【问题标题】:Canvas animations (window.requestAnimationFrame)画布动画 (window.requestAnimationFrame)
【发布时间】:2018-04-22 23:09:40
【问题描述】:

所以我是一个画布新手,我编写了一些代码来尝试创建动画。我想用抛物线方程让球移动,一切都很好,除了没有动画,我基本上得到了一个由弧线组成的抛物线。

这是我用于动画的一段代码:

// a b c are calculated in another function and they are used to calculate the parabola, x1 and y1 are the coordinates of the ball
function drawball(a,b,c,x1,y1){
    canvas=document.getElementById("mycanvas");
    ctx=canvas.getContext("2d");
    ctx.beginPath();
    ctx.arc(x1,y1,25,0,2*Math.PI);
    ctx.stroke();
    //stop when i get to the final point (x3 is a const)
    if(x1<x3){
        y1=a*(x1*x1)+b*x1+c; //parabola formula
        x1++;
        window.requestAnimationFrame(drawball(a,b,c,x1,y1));
    }
}

在 chrome 的控制台中我收到此错误:

Failed to execute 'requestAnimationFrame' on 'Window': The callback
provided as parameter 1 is not a function.

感谢您的帮助!

【问题讨论】:

    标签: javascript html animation canvas


    【解决方案1】:

    您正试图将drawball 函数的返回值 传递给requestAnimationFrame 回调(未定义)。

    下面是 chrome 控制台中的一个示例,当您尝试将值传递给 requestAnimationFrame 时,该值不是函数

    > requestAnimationFrame(console.log('hi'))
    

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

    相对于传递匿名函数:

    > requestAnimationFrame(() => { console.log('hi') })
    


    您需要传递一个函数,该函数将在 requestAnimationFrame 计时器结束时调用。

    一个例子是:

    // Vanilla Javascript
    window.requestAnimationFrame(function() { drawball(a,b,c,x1,y1) } );
    
    // ES6
    window.requestAnimationFrame(() => { drawball(a,b,c,x1,y1) } );
    

    在这些情况下,传递给requestAnimationFrame 的参数是一个函数,它将被调用并执行drawball 函数。

    【讨论】:

    • 感谢您的快速回答!所以我唯一需要做的就是用你的替换我的“requestAnimationFrame”,对吗?你能解释一下为什么这是必要的吗?我只是想了解,这样我才能提高自己。
    • @Deci 像其他函数一样 requestAnimationFrame 接受一个参数,但它不是一个字符串、一个整数或布尔值,而是一个实际的函数,它可以由父函数随时运行.如果你想想它是如何在幕后工作的,requestAnimationFrame 大约每 17 毫秒运行一次,所以它不想立即执行 drawball 函数它想知道它应该运行什么函数,等待 17 毫秒然后运行它。这是一个简化的解释,评论中只有这么多字符,但查看 MDN 了解更多。
    • 非常感谢您的耐心等待。现在动画效果很好。现在只有一个问题:它会留下一圈圈的痕迹。我试图在 x1 和 y1 的位置创建一个白色圆圈,以删除留下的圆圈,但结果是一堆灰色圆圈。那么如何删除旧的以便只有一个移动的圆圈呢?
    • @Deci 所以解释起来有点复杂,并不真正适用于这里的 cmets 部分,但这里有一个关于您的问题的 link to a good SO post。基本思想是每帧动画清除整个画布。一旦你这样做了,你会注意到闪烁,你需要实现双缓冲。 See this link
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多