每当我在浏览器中切换标签时,为什么当前标签会暂停?

时间:2017-12-27 13:19:35

标签: javascript animation three.js requestanimationframe

我使用 three.js 加载了navMesh和动物。动物正在地图上移动。但当我改变标签动物移动暂停时,如果再次打开那个标签动物再次从暂停点移动。如何播放继续动画,无论是标签更改还是标签背景。

Jsfiddle

function animate() {
            var currTime = window.performance.now();
            var delta = (currTime - lastFrameTime) / 1000;
            var dTime = Math.min(delta, maxFrameTime);
            elapsedTime += delta;
            lastFrameTime = currTime;

            tick(dTime);

            requestAnimationFrame( animate );
            render();
        }

2 个答案:

答案 0 :(得分:2)

这是setAnimationFrame工作中的一项功能。浏览器限制非活动选项卡上的处理以节省功耗和CPU周期。有关详细信息:https://stackoverflow.com/a/5927432/7316502

播放人们无法看到的动画是没有意义的。但是,根据目标点和速度,当用户返回标签时,更新背景中生物的位置并显示其当前位置可能是有意义的。

如果我理解正确的话,想要的结果就是点击一个点,让怪物开始移动,然后当你退去并退回标签时,好像怪物的移动量一样,就好像你一样正在看。

您可以使用Page Visibility API来帮助执行此操作:https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API

visibilityChange上,您可以查看是否window.hidden===true。如果是,请暂停模拟并等待visibilityChange的其他window.hidden===false事件。

当焦点返回选项卡时,计算当前时间与窗口隐藏时间之间的时差。将渲染快进到此时间点。然后继续显示动画。

以下是这可能是什么样子的示例。

我把它放在你的init()函数中。

function handleVisibilityChange() {
    if (document.hidden) {
        windowHidden=true;
        hideTime=window.performance.now();
    } else  {
        windowHidden=false;
        var timeDiff=(window.performance.now()-hideTime)/1000;
        console.log('Page invisible for ',timeDiff,' seconds, jump ahead.');
        tick(timeDiff);
        render();
    }
}
document.addEventListener("visibilitychange", handleVisibilityChange, false);

然后我检查了tick函数以检查windowHidden标记:

if (!level||windowHidden) { return; }

(几乎完成)示例:https://jsfiddle.net/thmsdnnr/thk80hsh/2/

请注意,这并不像你想要的那样有效:当前怪物只是在隐藏窗口时继续前往 next 节点的路径上。这就是为什么当你退回时,怪物离开路径,然后返回到它前往的最后一个节点,然后继续。

由于怪物正在追踪具有多个点和不同有向段的路径,因此您需要重构您的tick函数,或者(更好的选择,我认为)完全写另一个,这需要隐藏窗口的时间间隔,并根据速度和时间计算怪物通过的路径上的节点数,移除这些节点,并将怪物渲染到正确的位置。

答案 1 :(得分:0)

requestAnimationFrame 将当前时间传递给它调用的函数,因此您可以声明 function animate(currTime) {...},然后删除您自己的 currTime。在此示例中,delta 将是帧之间的时间量,或者是离开和返回到当前选项卡之间经过的时间量。

function animate(currTime) {  // <-- currTime is populated by requestAnimationFrame
    var delta = (currTime - lastFrameTime) / 1000;

    // I don't think you need dTime anymore

    elapsedTime += delta;
    lastFrameTime = currTime;

    tick(delta);

    requestAnimationFrame( animate );
    render();
}