开发过程中,遇到了小程序内嵌的网页小游戏在小程序点击右上角那个圆点退出时,游戏的音乐没有关闭,并且逻辑也没有停止。因为是内嵌的网页,因此,这个已经跳脱了小程序的生命周期,只能从网页层面入手,上网查了一些资料,发现了这个Visibilitychange事件
visibilitychange事件是浏览器新添加的一个事件,
当浏览器的某个标签页切换到后台,或从后台切换到前台时就会触发该消息,
现在主流的浏览器都支持该消息了,例如Chrome, Firefox, IE10等。
简单的说,浏览器标签页被隐藏或显示的时候会触发visibilitychange事件。
有些浏览器保留了前缀,需要对这些做一些兼容
this.statusBeforeHide = true; //记录游戏音乐开启关闭的状态
let hiddenProperty = ('hidden' in document) ? 'hidden' : ('webkitHidden' in document) ? 'webkitHidden' : ('mozHidden' in document) ? 'mozHidden' : null;
if (hiddenProperty) {
let visibilityChangeEvent = hiddenProperty.replace(/hidden/i, 'visibilitychange');
let onVisibilityChange = () => {
console.log('visibilityChange');
this.changePlay();
};
document.addEventListener(visibilityChangeEvent, onVisibilityChange);
} else {
console.log("This demo requires a browser, such as Google Chrome or
Firefox, that supports the Page Visibility API.");
}
private changePlay() {
// 页面隐藏
if (document["hidden"] || document["webkitHidden"] || document["mozHidden"]) {
if (this.statusBeforeHide) {
//停止音乐
}
} else {
if (this.statusBeforeHide) {
//播放音乐
}
}
}
HTML5中专门为document元素添加了相关属性和事件:
属性:
1、Document.hidden 只读属性 布尔值 简单的表示标签页显示或者隐藏
如果页面处于被认为是对用户隐藏状态时返回true,否则返回false。
2、Document.visibilityState 只读属性是一个用来展示文档可见性状态的字符串,可能的值:
visible: 页面内容至少是部分可见。
在实际中,这意味着页面是非最小化窗口的前景选项卡。
hidden : 页面内容对用户不可见。
在实际中,这意味着文档可以是一个后台标签,或是最小化窗口的一部分,或是在操作系统锁屏激活的状态下。
prerender : 页面内容正在被预渲染且对用户是不可见的(被document.hidden当做隐藏). 文档可能初始状态为prerender,但绝不会从其它值转为该值。 注释:浏览器支持是可选的。
unloaded : 页面正在从内存中卸载。 注释:浏览器支持是可选的。
3、Document.onvisibilitychange
EventListener 提供在visibilitychange 事件被触发时要调用的代码。
// 设置隐藏属性和改变可见属性的事件的名称
var hidden, visibilityChange;
if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
hidden = "hidden";
visibilityChange = "visibilitychange";
} else if (typeof document.msHidden !== "undefined") {
hidden = "msHidden";
visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
}
var videoElement = document.getElementById("videoElement");
// 如果页面是隐藏状态,则暂停视频
// 如果页面是展示状态,则播放视频
function handleVisibilityChange() {
if (document[hidden]) {
videoElement.pause();
} else {
videoElement.play();
}
}
// 如果浏览器不支持addEventListener 或 Page Visibility API 给出警告
if (typeof document.addEventListener === "undefined" || typeof document[hidden] === "undefined") {
console.log("This demo requires a browser, such as Google Chrome or Firefox, that supports the Page Visibility API.");
} else {
// 处理页面可见属性的改变
document.addEventListener(visibilityChange, handleVisibilityChange, false);
// 当视频暂停,设置title
// This shows the paused
videoElement.addEventListener("pause", function(){
document.title = 'Paused';
}, false);
// 当视频播放,设置title
videoElement.addEventListener("play", function(){
document.title = 'Playing';
}, false);
}
为了支持老版本的浏览器,我们需要对document.hidden在做一些前缀处理:
function getHiddenProp(){
var prefixes = ['webkit','moz','ms','o'];
// 如果hidden 属性是原生支持的,我们就直接返回
if ('hidden' in document) {
return 'hidden';
}
// 其他的情况就循环现有的浏览器前缀,拼接我们所需要的属性
for (var i = 0; i < prefixes.length; i++){
// 如果当前的拼接的前缀在 document对象中存在 返回即可
if ((prefixes[i] + 'Hidden') in document) {
return prefixes[i] + 'Hidden';
}
}
// 其他的情况 直接返回null
return null;
}
同样的,我们可以获取document.visibilityState属性:
function getVisibilityState() {
var prefixes = ['webkit', 'moz', 'ms', 'o'];
if ('visibilityState' in document) {
return 'visibilityState';
}
for (var i = 0; i < prefixes.length; i++) {
if ((prefixes[i] + 'VisibilityState') in document){
return prefixes[i] + 'VisibilityState';
}
}
// 找不到返回 null
return null;
}
你可以在document对象上注册一个监听visibilitychange事件,根据document.hidden或者document.visibilityState属性做一些业务逻辑:
var visProp = getHiddenProp();
if (visProp) {
// 有些浏览器也需要对这个事件加前缀以便识别。
var evtname = visProp.replace(/[H|h]idden/, '') + 'visibilitychange';
document.addEventListener(evtname, function () {
document.title = document[getVisibilityState()]+"状态";
},false);
}