全屏滚动网站的适配要求
既要自适应宽度,也要自适应高度。一般的网站只需要适配宽度即可,高度会自动随着宽度变动。所以一般的网站使用下面两种方案即可。
在实现h5适配常用的方法有:
-
插件
postcss-px2rem
将px转化为rem, 而rem通常通过插件lib-flexible
动态修改根节点html的font-size
属性。插件
lib-flexible
核心实现代码如下:
js
function refreshRem(){
var width = docEl.getBoundingClientRect().width;
if (width / dpr > 540) {
width = 540 * dpr;
}
var rem = width / 10;
docEl.style.fontSize = rem + 'px';
flexible.rem = win.rem = rem;
}
win.addEventListener('resize', function() {
clearTimeout(tid);
tid = setTimeout(refreshRem, 300);
}, false);
- 插件
postcss-px-to-viewport
将px转化为vh(vw/vh/vmin/vmax), 在定屏滚动时,通常将转换后的单位配置为vw。
-
为什么使用vmin实现全屏滚动网站PC端自适应不行?
PC的尺寸正常为1920*1080; 插件
postcss-px-to-viewport
转换vmin的公式是 代码中元素指定的px值 / 插件配置参数viewportWidth;使用vmin,当高度为1080,宽度在1080-1920之间时,都是以高度作为标准计算元素的大小,此时vmin===vh,只要当宽度在0-1080之间时,才会以宽度作为标准计算元素的大小。所以使用vmin的缺点就是在1080-1920区间无法做到自适应。
上面两个方案有各自的优点,但有个缺点,无法同时兼容 短屏和长屏**。**
优化后的实现方案
- 下面这段代码参考异人之下官网(yirenzhixia.qq.com/)实现。
实现逻辑:以PC正常尺寸1920*1080的比率作为衡量标准。当屏幕实际的宽高比大于标准时,以高度作为标准计算fontSize
值;当屏幕实际的宽高比小于标准时,以宽度作为标准计算fontSize
值。
js
function refreshRemNew2() {
const width = docEl.clientWidth
const height = docEl.clientHeight
let basePx = width
let rem
if (width / height >= 1.78) { // > 16:9
basePx = height * 1.78
} else {
}
rem = basePx / 38.4
docEl.style.fontSize = rem + 'px'
window.pxRatio = rem
if (navigator.userAgent.includes('Firefox') && navigator.userAgent.includes('Mobile'))
{
docEl.style.fontSize = rem * 0.9 + 'px'
window.pxRatio = rem * 0.9
}
flexible.rem = win.rem = rem;
}
- 下面这段代码参考洛克王国世界游戏官网(腾讯互动娱乐)实现。
实现逻辑: 通过宽高计算当前屏幕是短屏还是长屏,如果为正常屏或短屏就以宽度来计算根节点的font-size
, 如果为长屏就以高度为准来计算根节点的font-size
。
diff
- 短屏:高度远远大于宽度,高宽比大于正常的宽高比。
- 长屏:宽度远远大于高度,宽高比大于正常的宽高比。
这里的实现逻辑和上面类似,标准比率也是1.78 (2560 / 1440)。 这里做了更细致的划分。
js
function refreshRemNew() {
const screenWidth = document.documentElement.clientWidth;
const screenHeight = document.documentElement.clientHeight;
const screenRatio = Math.ceil(screenWidth / screenHeight * 1000) / 1000;
const standardRatio = Math.ceil(2560 / 1440 * 1000) / 1000;
const normalHighLimit = Math.ceil((standardRatio + .12) * 1000) / 1000;
const normalLowLimit = Math.ceil((standardRatio - .218) * 1000) / 1000;
const longLimit = Math.ceil((standardRatio + .25) * 1000) / 1000;
console.log(screenRatio, standardRatio)
console.log(normalHighLimit < screenRatio, longLimit >= screenRatio)
var rect = docEl.getBoundingClientRect()
console.log('rect', rect, screenHeight)
var width = rect.width;
var height = Math.max(screenHeight, rect.height);
if (width < 750) {
width = 750;
}
var rem = width / 10;
if (normalLowLimit <= screenRatio && normalHighLimit >= screenRatio) {
console.log('不用调整间距')
} else if (screenRatio < normalLowLimit) {
console.log('短屏');
} else if (normalHighLimit < screenRatio && longLimit >= screenRatio) {
console.log('长屏');
rem = height / 5;
} else if (longLimit < screenRatio) {
console.log('超长屏');
rem = height / 5;
} else {
console.log('意料之外的尺寸范围')
}
console.log('rem', rem, 'height', height, 'width', width)
docEl.style.fontSize = rem + 'px';
flexible.rem = win.rem = rem;
}