背景
有时候我们的 H5 应用既要能运行在各种容器内,也要能运行在浏览器中,并且在容器中尽量采用沉浸式方式呈现。
在容器中,是需要根据不同容器来设置不同的状态栏背景色的,不然就很可能看不见系统展示在状态栏上的文字了。而在浏览器中,不采用沉浸式方式呈现,因此是不需要理会的。
方案
可以借助 window.innerHeight 和 window.screen.height 来判断,关于这俩的含义,可以在 MDN 上查到。
实际上,在移动端,H5 页面中,window.screen.height 拿到的是逻辑像素值,window.innerHeight 拿到的是物理像素值或者逻辑像素值。并且,在页面初始化过程中,window.innerHeight 有可能会发生变化(最后稳定的值才是正确的)。
为了应对上述情况,必须要在初始化的时候不停地检查,直到最终拿到稳定结果。
《First, Understand Your Screen》
代码
async function isImmersion() {
const check = () => {
// windowHeight 是期望存储视口的逻辑像素值
let windowHeight = window.innerHeight / window.devicePixelRatio;
if (
// 如果 window.screen.height 比 window.innerHeight 大,
// 说明 window.innerHeight 肯定是逻辑像素值。
window.screen.height - window.innerHeight > 0
&& window.screen.height - window.innerHeight < 130
) {
windowHeight = window.innerHeight;
}
// iPhone X 飞猪下面 window.screen.height 和 windowHeight 差一丢丢(其余场景都可以用相等来判断)。
return window.screen.height - windowHeight < 1;
};
if (document.readyState !== 'complete') {
await new Promise((resolve) => {
document.addEventListener('DOMContentLoaded', resolve);
});
}
return new Promise((resolve, reject) => {
const checkResults = [];
setTimeout(() => {
checkResults.push(check());
const length = checkResults.length;
if (
length >= 3
&& checkResults[length - 1] === checkResults[length - 2]
&& checkResults[length - 2] === checkResults[length - 3]
) {
resolve(checkResults[length - 1]);
}
}, 100);
setTimeout(() => {
reject(new Error('Check immersion timeout.'));
}, 1000);
});
}
网友评论