requestAnimationFrame API - 在密集的JavaScript函数中制作动画。

问题描述 投票:1回答:1

我在一个web应用中,有一个长时间取用、线程阻塞的功能,在其执行过程中,我想显示一个动画图标。在其执行过程中,我想显示一个动画图标。我想使用Window.RequestAnimationFrame()requestAnimationFrame(). 我的工作来源是。


我知道,我需要一个函数--我把它叫做 animateLoadingIcon() - ,以更新我的绘图。在它的函数体中,我最后必须调用 requestAnimationFrame(animateLoadingIcon) 来启动视图的递归更新。

在下面找到函数animateLoadingIcon,它根据调用后所经过的时间,计算图标的旋转角度。

function animateLoadingIcon() {
rotateCount = (new Date().getTime() - starttime) / 3;
if (rotateCount > 359) {
  rotateCount %= 360;
}
divLoadingIcon.style.transform = 'rotate(' + rotateCount + 'deg)';
requestedAnimationFrame = requestAnimationFrame(animateLoadingIcon);

}

我原本想执行的函数是calc(),其中调用了animateLoadingIcon()。

function calc() {

let randomMills = Math.random()*6000;
console.log("Start with duration: " + randomMills +"ms.")

starttime = new Date().getTime();
let recentTime = new Date().getTime();

let i = 0;

animateLoadingIcon();   
while (recentTime < starttime+randomMills) {
    i++;
    isPrime(i);
    recentTime = new Date().getTime();

} 
cancelAnimationFrame(requestedAnimationFrame);    

}

我希望当我点击按钮时,轮子能转动,当离开while-loop时,轮子能停止。然而,它却没有。谁能指出我的错误?

请看下面一个jsfiddle的例子https:/jsfiddle.net71vqarLs8

javascript requestanimationframe
1个回答
1
投票

窗口.请求动画帧 会是一个更好的解决方案,也是 "正确 "的方式。

使用承诺和 asyncawait使用setTimeout循环代替while循环,这样每次对isPrime的调用和每次循环迭代都在事件循环中延时,并允许动画在其间执行。

jsfiddle演示。https:/jsfiddle.netcxews089

  await new Promise(res => {
    var loop = () => {
      var tid = setTimeout(() => {
        if (recentTime < starttime + randomMills) {
          i++;
          isPrime(i);
          recentTime = new Date().getTime();
          loop()
        } else {clearTimeout(tid);res();}
      }, 0)
    };
    loop()
  });

不太美观,肯定可以写得更优雅,但可以用。 可能一个异步函数循环也可以作为一个单行的等价物。当然会有开销,你可能想对isPrime或其他任何你要调用的函数进行分块调用。


1
投票

感谢所有有用的意见。关于将线程阻塞的while-loop外包给worker的提示很有针对性。

我现在基本上只调用

function calc() {

    animateLoadingIcon();   
    worker.postMessage([randomMills, starttime])

}

而当worker发出准备好的事件时,我就执行。

worker.onmessage = function (e) {
    cancelAnimationFrame(requestedAnimationFrame);
}

这就把阻塞代码放到了一个单独的线程中, 而requestAnimationFrame可以在主线程中安然运行。

© www.soinside.com 2019 - 2024. All rights reserved.