Web移動端實現自適應縮放界面的方法彙總

「關注  前端開發社區 ,回覆「 1」 便可加入  前端技術交流羣,回覆  「 2」 便可免費領取500G前端乾貨!javascript

 
做者 | 唐宋元明清2188
來源 | http://www.cnblogs.com/kybs0/

在開發App端的網頁時,要適配iphone、ipad、ipod、安卓等各類機型,通常是直接使用em、px轉em、界面縮放。
本章是經過將界面縮放,等比例顯示在各機型上。過程當中遇到了些問題和大坑~
而後下面是具體的自適應實現方式的嘗試~

方案一:設置tranform/scale

首先設置內容固定寬度、自動高度(如下舉例)

 width: 375px; height: auto;
經過獲取窗口的寬度與固定寬度相除,得到縮放比例
const scaleValue=window.innerWidth / 375
在html層,添加一段script:
<script dangerouslySetInnerHTML={{ __html: this.getScript() }}></script>
添加一段設置zoom值的函數:
    
  
  
  
   
   
            
   
   

    
  
  
  
   
   
            
   
   
getScript() { return ` const zoomValue=window.innerWidth / 375; document.documentElement.style.transform="scale("+zoomValue+")"; document.documentElement.style.transformOrigin="left top";     ; }
注:
以上也能夠直接寫script,我上面返回一段html是由於項目是經過服務端渲染的。
樣式的設置必須在界面加載以前,不然會因界面顯示變動出現閃現問題。
由於添加了服務端渲染,因此沒法在界面一開始初始時,沒法獲取window、document等對象。而上面html的注入,對服務端渲染機制的一個黑科技~
上面的方案完成後,看看效果。而後坑出來了:
  1. 項目設置的absolue元素width 100%失效了 -- 能夠設置固定的寬度解決css

  2. 彈框position=fixed位置飛到天邊去了 -- 這個沒法規避。html

網上找到了一篇文章 CSS3 transform對普通元素的N多渲染影響 ,介紹了transform的一堆坑。
我這個項目一些佈局須要position=fixed,因此tranform不適合~放棄
這個坑的其它介紹能夠參考下:
  • transform限制position:fixed的跟隨效果前端

  • 關於在transform下的子元素設置fixed無效的困惑java

總結:
  1. position:fixed不支持,因此想作標題欄置頂,上面方案是沒法實現的。ios

  2. ipad有遺留問題:微信瀏覽器,橫豎屏切換時,有些機型在打開一瞬間,橫向拖動有空白問題。這個問題沒法處理~瀏覽器

  3. 以上方案由於使用了scale,同時窗口的寬高window.innerHeight沒法準確獲取,須要除以比例,好比: window.innerHeight / (window.innerWidth / 375)微信

方案二:設置zoom

在上一個方案的基礎上,嘗試zoom縮放:
    
  
  
  
   
   
            
   
   

    
  
  
  
   
   
            
   
   
getScript() {return `const zoomValue=window.innerWidth / 375;document.documentElement.style.zoom = zoomValue;;}
emmm,很簡單,調試效果看起來很不錯。模擬機上,看起來都正常~
可是坑來了:真機有問題,發如今ipad的safari上,頁面是放大了,可是字段根本就沒變化!
緣由居然是:蘋果在ipad的網頁,改動渲染方面的相關規則。有點坑~
https://apple.stackexchange.com/questions/377216/css-zoom-does-not-work-ipad-os-v13-latest-safari
https://stackoverflow.com/questions/7907760/why-the-font-size-wont-change-with-browser-zoom-in
實現沒辦法,我後面嘗試, 經過userAgent對ipad機型(ipad、macintosh)特殊處理,直接獲取全部包含了文字的div、p、span等元素,放大font-size。
發現能夠處理,沒毛病!可是也有些缺陷,沒辦法在一開始處理字體,由於元素尚未初始化,而等界面加載後再刷字體大小,界面會閃現一次。

方案三:設置viewport-scare

在html中添加默認viewport:
    
  
  
  
   
   
            
   
   

    
  
  
  
   
   
            
   
   
<meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1,user-scalable=no, minimal-ui"></meta>
ps:minimal-ui 與本文無關,它能夠在safari加載網頁時隱藏地址欄與導航欄
添加viewport更新:
    
  
  
  
   
   
            
   
   

    
  
  
  
   
   
            
   
   
getScript() { return `const zoomValue=window.innerWidth / 375;var viewport = document.querySelector("meta[name=viewport]");viewport.content="width=device-width,initial-scale="+zoomValue+", maximum-scale="+zoomValue+", minimum-scale="+zoomValue+",user-scalable=no, minimal-ui" ; }
運行代碼,emmm,有一些小問題。
  • margin:auto,在某些佈局下會讓頁面偏移 -- 刪除就好app

  • 設置background-image的區域,背景圖片並無填充滿 -- 添加width:100%解決iphone

  • position:fixed,寬高顯示有問題 -- 設置固定寬度,好比375px,固定高度;若是須要全屏,可使用height: 100vh。

fixed佈局建議:以彈框爲例
添加fixed佈局的容器,水平豎直方向靠邊距離分別設置一個就好了,left:0,bottom:0。
而後添加absolute佈局的內容容器.若是須要居中,能夠在js中設置bottom=window.innerHeight / 2 - 元素的高度/2
總結:
  • 以上方案不支持fixed佈局,修改完成後,ipad的水平滾動條依然存在,沒法解決

兼容適配

採用第二個zoom縮放方案,同時對ipad機型特殊處理,另外採用scale縮放方案。
完整代碼以下:
1. 初始化適配(支持服務端渲染)
html-header添加script
    
  
  
  
   
   
            
   
   

    
  
  
  
   
   
            
   
   
{/* app contentAutoFit */} <script dangerouslySetInnerHTML={{ __html: this.getZoomScript() }}></script>
自適應可執行代碼文本。
    
  
  
  
   
   
            
   
   

    
  
  
  
   
   
            
   
   
//返回自適應html字符串 getZoomScript() { return ` const zoomValue = window.innerWidth / 375; const userAgentInfo = window.clientInformation.appVersion; //若是是ipad if (userAgentInfo.indexOf("iPad") != -1 || userAgentInfo.indexOf("Macintosh") != -1) { //內容自適應 - 設置transform-scale。 //fixed佈局時須要修改下left/margin-left等,同時窗口的寬高沒法準確獲取,須要除以比例,詳見windowSizeWithScaleHelper //ipad有遺留問題:微信瀏覽器加載時,橫豎屏切換一瞬間,有空白問題。不過能夠忽略~ document.documentElement.style.transform = "scale(" + zoomValue + "," + (zoomValue < 1 ? 1 : zoomValue) + ")"; document.documentElement.style.transformOrigin = "left top"; var html = document.querySelector("html"); html.style.width = '375px'; html.style.overflow = 'hidden'; html.style.overflowY = 'auto'; } else { //內容自適應 - 設置zoom。經過zoom來縮放界面,在ipad的safari瀏覽器等會存在字體沒法縮放的兼容問題。 document.documentElement.style.zoom = zoomValue; } // 內容自適應 - 設置viewport,總體okay。可是ipad的水平滾動條沒法解決 // var viewport = document.querySelector("meta[name=viewport]"); // viewport.content = "width=device-width,initial-scale=" + zoomValue + ", maximum-scale=" + zoomValue + ", minimum-scale=" + zoomValue + ",user-scalable=no, minimal-ui" `; }
2. 添加加載及界面變動刷新機制
  • 微信瀏覽器橫豎屏切換時,某些機型不會觸發窗口大小變動,因此須要額外添加orientationchange監聽

  • 加載過程當中,微信瀏覽器切換橫豎屏會有顯示問題,須要加載完成後適配

    
  
  
  
   
   
            
   
   

    
  
  
  
   
   
            
   
   
componentDidMount() { //window.onresize = this.adjustContentAutoFit; //解決微信橫豎屏問題 window.addEventListener("orientationchange", this.adjustContentAutoFit); //解決加載過程當中,切換橫豎屏,致使界面沒有適配的問題 this.adjustContentAutoFit(); } componentWillUnmount() { window.removeEventListener("orientationchange", this.adjustContentAutoFit); } //監聽窗口尺寸變動,刷新自適應 adjustContentAutoFit() { const zoomValue = window.innerWidth / 375; const userAgentInfo = window.clientInformation.appVersion; //若是是ipad if (userAgentInfo.indexOf("iPad") != -1 || userAgentInfo.indexOf("Macintosh") != -1) { //內容自適應 - 設置transform-scale。 //fixed佈局時須要修改下left/margin-left等,同時窗口的寬高沒法準確獲取,須要除以比例,詳見windowSizeWithScaleHelper //ipad有遺留問題:微信瀏覽器,橫豎屏切換時,有些機型在打開一瞬間,有空白問題。不過能夠忽略~ document.documentElement.style.transform = "scale(" + zoomValue + "," + (zoomValue < 1 ? 1 : zoomValue) + ")"; document.documentElement.style.transformOrigin = "left top"; var html = document.querySelector("html") as HTMLElement; html.style.width = '375px'; html.style.overflow = 'hidden'; html.style.overflowY = 'auto'; } else { // 內容自適應 - 設置zoom。經過zoom來縮放界面,在ipad的safari瀏覽器等會存在字體沒法縮放的兼容問題。 document.documentElement.style.zoom = zoomValue; } // 內容自適應 - 設置viewport,總體okay。可是ipad的水平滾動條沒法解決 // var viewport = document.querySelector("meta[name=viewport]"); // viewport.content = "width=device-width,initial-scale=" + zoomValue + ", maximum-scale=" + zoomValue + ", minimum-scale=" + zoomValue + ",user-scalable=no, minimal-ui" }
此方案的一些小遺留問題:
  • ipad不支持position:fixed,因此沒法實現標題欄置頂等功能

  • 微信瀏覽器,橫豎屏切換時,有些機型在打開一瞬間,有空白問題

參考:
  • IOS環境下固定定位position:fixed帶來的問題與解決方案

  • 小技巧css解決移動端ios不兼容position:fixed屬性,無需插件

  • 踩坑路上——IOS Safari瀏覽器下固定定位position:fixed帶來的問題與解決方案

  • iphone safari不支持position fixed的解決辦法

  • orientationchange事件、監測微信移動端橫豎屏

本文完~
   
請各位帥哥美女多多支持帥編,回覆 「 1」  便可加入 前端技術交流羣 ,回覆 「 2」  便可領取500G前端乾貨

本文分享自微信公衆號 - 前端開發社區(pt1173179243)。
若有侵權,請聯繫 support@oschina.cn 刪除。
本文參與「OSC源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。

相關文章
相關標籤/搜索