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

why does current tab pause every time when I switch tabs in browser?

我使用 three.js 加载了导航网格和动物。动物在地图上移动。但是当我更改标签动物移动暂停时,如果再次打开该标签动物从暂停点再次移动。如何在选项卡更改或选项卡背景下播放继续动画。

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();
        }

这是setAnimationFrame工作中的一个特点。浏览器限制对非活动选项卡的处理以节省功耗和 CPU 周期。更多信息:

播放人们看不到的动画是没有意义的。但是,在给定目标点和速度的情况下,更新生物在后台的位置并在用户 returns 到选项卡时显示其当前位置可能是有意义的。

如果我没理解错的话,期望的结果是点击一个点,让怪物开始移动,然后当你离开和返回时,就好像怪物移动了与你正在观看的相同的量.

您可以使用页面可见性 API 来帮助做到这一点:https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API

visibilityChange 上,您可以查看是否 window.hidden===true。如果是这样,请暂停模拟并等待另一个 visibilityChange 事件 window.hidden===false.

当焦点 returns 到选项卡时,计算当前时间与 window 隐藏时间之间的时间差。将渲染快进到这个时间点。然后继续显示动画。

这是一个示例。

我把它放在你的 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/

请注意,这并不完全符合您的预期:目前怪物只是在通往 下一个 节点的路径上前进,而 window 是隐藏的.这就是为什么当您向后移动时,怪物会偏离路径,返回到它前往的最后一个节点,然后继续。

由于怪物沿着一条有多个点和不同定向线段的路径行进,您需要重构您的 tick 函数,或者(我认为更好的选择)完全编写另一个函数,这需要window 隐藏的时间间隔,并计算怪物在给定速度和时间的情况下通过的路径上的节点数,移除这些节点,并在正确的位置渲染怪物。

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();
}