cocos creator做H5游戏,切换浏览器标签

一、cocos creator相关处理

cocos creator做的H5游戏,切换浏览器标签,发现一切都停止了。在creator论坛上,也看到了相关的讨论:
切换标签页,动作动画都暂停了
我做了一个网游,页面切换或最小化时,所有js暂停,怎么解决?

有个层主提供了使用worker解决办法

//bgWorker.js
function timedCount()
{
    postMessage(1);
    setTimeout("timedCount()", 1000 / 60);
}

timedCount();

//要后台跑的scene加上这个
onEnterBackground : function()
{
    console.log("游戏进入后台");
    if(!cc.sys.isNative)
    {
        this.bgWorker = new Worker("res/bgWorker.js");
        this.bgWorker.onmessage = function(evt)
        {
            cc.director.mainLoop();
        };
    }else {

    }
},

onEnterForeground : function()
{
    console.log("游戏回到前台");

    if(!cc.sys.isNative)
    {
        if(this.bgWorker != null)
        {
            this.bgWorker.terminate();
            this.bgWorker = null;
        }
    }else{

    }
}

不用每个计时器都用一个worker,一个worker在进后台的时候按帧率,每隔一段时间调一次cc.director.mainLoop()就行了。

二、Laya中切换浏览器标签,不会暂停掉
1.Stage.as
// 各种浏览器兼容
var hidden:String = "hidden", state:String = "visibilityState",
 visibilityChange:String = "visibilitychange";
var document:* = window.document;
if (typeof document.hidden !== "undefined") {
    visibilityChange = "visibilitychange";
    state = "visibilityState";
} else if (typeof document.mozHidden !== "undefined") {
    visibilityChange = "mozvisibilitychange";
    state = "mozVisibilityState";
} else if (typeof document.msHidden !== "undefined") {
    visibilityChange = "msvisibilitychange";
    state = "msVisibilityState";
} else if (typeof document.webkitHidden !== "undefined") {
    visibilityChange = "webkitvisibilitychange";
    state = "webkitVisibilityState";
}

window.document.addEventListener(visibilityChange, visibleChangeFun);
function visibleChangeFun():void {
    if (Browser.document[state] == "hidden") {
        _isVisibility = false;
        if (_me._isInputting()) Input["inputElement"].target.focus = false;
    } else {
        _isVisibility = true;
    }
    renderingEnabled = _isVisibility;
    _me.event(Event.VISIBILITY_CHANGE);
}
2.Render.as
function Render(width,height){
    /**@private */
    this._timeId=0;
    var style=Render._mainCanvas.source.style;
    style.position='absolute';
    style.top=style.left="0px";
    style.background="#000000";
    Render._mainCanvas.source.id="layaCanvas";
    var isWebGl=laya.renders.Render.isWebGL;
    Render._mainCanvas.source.width=width;
    Render._mainCanvas.source.height=height;
    isWebGl && Render.WebGL.init(Render._mainCanvas,width,height);
    Browser.container.appendChild(Render._mainCanvas.source);
    Render._context=new RenderContext(width,height,isWebGl ? null :Render._mainCanvas);
    Render._context.ctx.setIsMainContext();
    Browser.window.requestAnimationFrame(loop);
    function loop (){
        Laya.stage._loop();
        Browser.window.requestAnimationFrame(loop);
    }
    Laya.stage.on("visibilitychange",this,this._onVisibilitychange);
}


/**@private */
private var _timeId:int = 0;

/**@private */
private function _onVisibilitychange():void {
    if (!Laya.stage.isVisibility) {
        _timeId = Browser.window.setInterval(this._enterFrame, 1000);
    } else if (_timeId != 0) {
        Browser.window.clearInterval(_timeId);
    }
}

/**@private */
private function _enterFrame(e:* = null):void {
    Laya.stage._loop();
}

可以看到,切换标签进入后台后,Laya会使用浏览器的setInterval方法,每秒一次,继续处理_loop。这个频率已经很低了,因为在正常状态下,是使用Browser.window.requestAnimationFrame来处理_loop的。

在https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestAnimationFrame看到如下解释:

window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行
.
注意:若你想在浏览器下次重绘之前继续更新下一帧动画,那么回调函数自身必须再次调用window.requestAnimationFrame()
.
当你准备更新动画时你应该调用此方法。这将使浏览器在下一次重绘之前调用你传入给该方法的动画函数(即你的回调函数)。回调函数执行次数通常是每秒60次,但在大多数遵循W3C建议的浏览器中,回调函数执行次数通常与浏览器屏幕刷新次数相匹配。为了提高性能和电池寿命,因此在大多数浏览器里,当requestAnimationFrame() 运行在后台标签页或者隐藏的