引用场景
做 web 游戏时,通常游戏是嵌入到 app 内部,通过 app 内部入口,跳转进入所开发的 web 游戏,app 内会预留返回功能,web 游戏可以使用 webview 自带的返回,实现游戏内不同场景的跳转。
比如游戏内有 a、b、c 三个场景,其中 a 场景是启动页面,a 场景进入 b 场景,b 场景进入 c 场景,从 c 场景中点返回,回到 b 场景,从 b 场景中点击返回,回到 a 场景, 从 a 场景中点击返回,调用 webview自身的返回事件。最后的效果如下图:
事件监听
当浏览器活动历时记录条目更改时,将触发 popstate 事件,如用户点击浏览器的回退按钮,或者在 javascript 代码中调用 history.back() 或者 history.forward() 方法,所以只需要在需要监听事件的场景
window.addEventListener('popstate',
e => {
//添加点击返回处理逻辑
},
false
);
事件的消费和添加
仅仅监听事件,还是不够的,虽然写了监听逻辑,但是浏览器本身的返回事件还是触发的,这时候点击返回,还是会继续回到之前页面,所以需要添加一个新的状态,让浏览器不跳转到前一个页面,就需要用到 history.pushState() 方法。
history.pushState() 方法,是向当前浏览器会话的历史堆栈中添加一个状态 (state) ,添加以后,点击浏览器的返回,会消耗掉会话历史堆栈中栈顶的状态,也就是我们注册的最新的状态。
let state = {
title: "title",
url: null
};
window.history.pushState(state, "title", null);
其中 title 是标题,目前浏览器基本上是忽略这个参数,可以不管,url 是跳转地址,游戏内不需要跳转其他地址,直接传 null 即可。
事件的全局控制
使用 cocos creator 开发游戏,注册 popstate 监听事件后,在浏览器点击返回时,会在每个注册的位置触发,实际游戏场景中,只需要执行一次就够。
比如有 3 个游戏场景 a、b、c,从 a 中点击进入 b,从 b 中点击进入 c,b 和 c 内都注册了事件,这时候如果 b 和 c 分别直接注册,都会触发,导致界面显示出错。
像上述场景,就需要整体控制事件的添加和注册,每次添加事件和注册回调,放置到一个堆栈顶部,当事件触发时,从栈顶取出最新的一个,进行回调就行。
export default class PopStateMgr{
/**
* @desc: 注册返回事件
* @param {type}
* @return:
*/
static push(onBackClick:any){
PopStateMgr._events.push(onBackClick);
let state = {
title: "title",
url: null
};
window.history.pushState(state, "title", null);
window.addEventListener('popstate',
e => {
PopStateMgr._onBackClick();
},
false
);
}
private static _onBackClick(){
if(PopStateMgr._events.length <= 0){
return;
}
let func = PopStateMgr._events.pop();
if(func != null){
func();
}
}
private static _events:any[] = [];
}
类似上面这种,在需要监听返回事件的场景脚本组件内,调用 push 及触发的回调事件就行。如本实例中,就在 b 场景开始时,调用 push 注册事件。