簡單描述下需求場景:
本來開發的頁面在大部分手機裡,都是豎向下來展開的,但現在市場上摺疊手機越來越多,那麼當使用者翻轉折疊手機,寬度變長了,原本我們的開發頁面就會被拉大,顯得不好看,所以需要前端針對摺疊屏進行相容,在沒開啟的時候正常顯示,翻轉開啟的時候就把頁面上的div結合百分比和flex佈局展開成兩列。改善體驗。
沒做相容之前的摺疊屏效果如下:
做了相容後,同樣的螢幕大小開啟效果如下:
1. 首先更改全域性rem的計算方式,按照vue和react專案,都是放在index.html的js中,專案進入載入邏輯。
以前正常手機都是1,但摺疊屏情況下,要按0.5算,小一半螢幕
function resize() { !function (e) { function t(a) { if (i[a]) return i[a].exports; var n = i[a] = { exports: {}, id: a, loaded: !1 }; return e[a].call(n.exports, n, n.exports, t), n.loaded = !0, n.exports } var i = {}; return t.m = e, t.c = i, t.p = "", t(0) }([function (e, t) { "use strict"; Object.defineProperty(t, "__esModule", { value: !0 }); var i = window; var benchmarkWidth = 750; t["default"] = i.flex = function (e, t) { var a = e || 100 , n = t || 1 , r = i.document , o = navigator.userAgent , d = o.match(/Android[\S\s]+AppleWebkit\/(\d{3})/i) , l = o.match(/U3\/((\d+|\.){5,})/i) , c = l && parseInt(l[1].split(".").join(""), 10) >= 80 , p = navigator.appVersion.match(/(iphone|ipad|ipod)/gi) , s = i.devicePixelRatio || 1; p || d && d[1] > 534 || c || (s = 1); var u = 1 / s , m = r.querySelector('meta[name="viewport"]'); m || (m = r.createElement("meta"), m.setAttribute("name", "viewport"), r.head.appendChild(m)); m.setAttribute("content", "width=device-width,user-scalable=no,initial-scale=" + u + ",maximum-scale=" + u + ",minimum-scale=" + u); var offsetWidth = i.document.documentElement.offsetWidth; let percentage = 1 // 寬屏、摺疊屏縮小頁面比例 try { const scale = window.innerWidth / window.innerHeight if (scale >= 0.9) { percentage = 0.5 } } catch { } r.documentElement.style.fontSize = offsetWidth / benchmarkWidth * e * percentage + "px"; window.screenfontSize = offsetWidth / benchmarkWidth * e * percentage } , e.exports = t["default"] } ]); flex(100, 1); }
同時要在頁面中做監聽
resize() var pageWidth = window.innerWidth var t = null var fn = 'orientationchange' in window ? 'orientationchange' : 'resize'; window.addEventListener(fn, function () { clearTimeout(t) t = setTimeout(function () { var newPageWidth = window.innerWidth if (pageWidth !== newPageWidth) { pageWidth = newPageWidth resize() } }, 300) }, false);
2. 在對應要做相容的頁面中,進入頁面同樣執行 window.innerWidth / window.innerHeight 算出當前螢幕對應比例值,這裡以react為例子,vue轉換下寫法一樣的
import React, { useState, useEffect } from 'react'; function MyComponent() { const [hmScale, setHmScale] = useState(window.innerWidth / window.innerHeight); // 比例值 // 相容摺疊屏等系列獲取scale const getWidthScreen = () => { // 監聽開始初始化最新值 setHmScale(window.innerWidth / window.innerHeight) // 二次預防措施 let t = null let pageWidth = window.innerWidth clearTimeout(t) t = setTimeout(function () { let newPageWidth = window.innerWidth if (pageWidth !== newPageWidth) { pageWidth = newPageWidth setHmScale(window.innerWidth / window.innerHeight) } }, 300) } useEffect(() => { window.addEventListener('resize', getWidthScreen) return () => { // 解除安裝時移除監聽 window.removeEventListener('resize', getWidthScreen) } }, []) return ( <div> <div className={`detail-page ${hmScale >= 0.9 ? 'width-screen' : ''}`}> <div>1 </div> <div>2 </div> </div> </div> ); } export default MyComponent;
3. 得出scale後更改原本佈局下的div樣式,用百分比計算減去對應外邊距的rem,再用flx佈局就可以完成響應式摺疊屏相容。css參考如下:
.detail-page { &.width-screen { display: flex; flex-wrap: wrap; & > div { width: calc((100% - .2rem) / 2); &:nth-child(even) { margin-left: .2rem; } } } }
以上則就是相容摺疊屏的基本方法,如果是三屏,理論上就除以3,實際真機沒測試過。