1. 程式人生 > >阿里antd-mobile移動高清rem方案 不相容chart 和 app webview 在安卓下錯亂問題

阿里antd-mobile移動高清rem方案 不相容chart 和 app webview 在安卓下錯亂問題

前言

最早基於手淘做過一次H5 rem適配, 當時基於Hybrid APP。後面使用antd-mobile後,使用 阿里的高清方案。css 新增calc 函式 可以處理邊框 配合 flex佈局。但是字型大小要額外處理,並且部分安卓機型不支援calc,以及1px問題。so,最後我還是決定採用阿里的rem。這也是踩坑的開始

內嵌rn webview。

我們為三方提供一個H5授權頁,用於oAuth2 認證流程。在上述js計算,在ios下都正常。但是在安卓出現不識別問題。出現問題主要原因如下。

  1. 用rem佈局的H5頁面
  2. 頁面內嵌在APP的webview中
  3. 手機 設定 修改了預設字型大小

後續找到幾種解決方案,

(一)獲取系統字型大小

一般設計稿750px,為了便於計算,我們設1rem = 100px;也就是1rem = 1 * htmlFontSize (htmlFontSize 為 html 元素的字型大小),當然在iPhone6 375px寬的螢幕上,htmlFontSize 為50px。

其實,htmlFontSize 除了以px為單位外,還可以用百分比作為單位,比如你可以設定htmlFontSize的大小為312.5%,頁面的佈局效果與設定htmlFontSize 大小為50px是一樣的效果。

但是在有些 Android 手機上,瀏覽器或 webview 的預設字型是隨著系統設定的字型改變的。這樣就會導致預設字型大於或小於 16px。從這個思路出發,我們只需要找到系統設定的字型大小就可以正確的計算htmlFontSize的值了。所以有了以下獲取預設字型大小的函式。

// 獲取系統預設字型大小
// designWidth 設計稿的寬度
// rem2px 設計稿寬度下,1rem的寬度
function adapt(designWidth, rem2px){
    var d = window.document.createElement('div');
    d.style.width = '1rem';
    d.style.display = "none";
    var head = window.document.getElementsByTagName('head')[0];
    head.appendChild(d);
    var defaultFontSize = parseFloat
(window.getComputedStyle(d, null).getPropertyValue('width')); return defaultFontSize };

然後配合之前的htmlSize函式

!(function(doc, win, designWidth, rem2px) {
    var docEl = doc.documentElement,
       defaultFontSize = adapt(designWidth, rem2px),
       resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
       recalc = function() {
           var clientWidth = win.innerWidth
                        || doc.documentElement.clientWidth
                        || doc.body.clientWidth;

           if (!clientWidth) return;
           if (clientWidth < 750) {
               docEl.style.fontSize = clientWidth / designWidth * rem2px / defaultFontSize * 100 + '%';

           } else {
               docEl.style.fontSize = '625%';
           }
       };
    if (!doc.addEventListener) return;
    win.addEventListener(resizeEvt, recalc, false);
    doc.addEventListener('DOMContentLoaded', recalc, false);

})(document, window, 750, 100);

總結:這種方式能解決rem在安卓錯亂問題,但是會遇到頁面字型大小根據系統設定改變的問題,因為iphone6頁面其實還是375,沒進行放大 然後scale。所以能解決antd-mobile 類似下拉外掛需要使用 window.devicePixelRatio 來設定問題,對應chart 圖示也不會亂,也可以用rem處理字型,但是在pc開啟就很奇怪。

(二)獲取html元素實際寬度

一般,我們動態計算好html的font-size之後,我們就啥都不幹了,就走了。但是,我們現在知道了,我們設定的大小不一定是真實的大小,所以,我們需要在設定完字型大小之後,再去重新獲取一下html的font-size,看看實際的這個值,和我們設定的是不是一樣。如果不一樣,就要根據比例再設定一次。

function htmlFontSize(){
    var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
    var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
    var width = w > h ? h : w;
    width = width > 720 ? 720 : width
    var fz = ~~(width*100000/36)/10000
    document.getElementsByTagName("html")[0].style.cssText = 'font-size: ' + fz +"px";
    var realfz = ~~(+window.getComputedStyle(document.getElementsByTagName("html")[0]).fontSize.replace('px','')*10000)/10000
    if (fz !== realfz) {
        document.getElementsByTagName("html")[0].style.cssText = 'font-size: ' + fz * (fz / realfz) +"px";
    }
}

總結:這種方案沒使用過,可以自己試下。

(三)客戶端固定webview字型大小

移動端同學進行處理,在APP內直接設定webview的預設字型大小。
如:在每個webview配置webview.getSettings().setTextZoom(100)就可以了。

類似微信的 iOS 版的調整字型大小使用的是通過給 body 設定 -webkit-text-size-adjust:120% 屬性實現的,Android 則是通過 Java 呼叫 webview 的 API 設定字型大小。

(四)rem 閃屏問題

配合方案一的

@media (min-width: 320px){html{font-size: 266.667%;} }
@media (min-width: 360px){html{font-size: 300%;} }
@media (min-width: 375px){html{font-size: 312.5%;;} }
@media (min-width: 384px){html{font-size: 320%;} }
@media (min-width: 414px){html{font-size: 345%;} }
@media (min-width: 448px){html{font-size: 373.333%;} }
@media (min-width: 480px){html{font-size: 400%;} }
@media (min-width: 512px){html{font-size: 426.667%;} }
@media (min-width: 544px){html{font-size: 453.333%;} }
@media (min-width: 576px){html{font-size: 480%;} }
@media (min-width: 608px){html{font-size: 506.667%;} }
@media (min-width: 640px){html{font-size: 533.333%;} }
@media (min-width: 750px){html{font-size: 625%;;} } 

注意:引入檔案時,方案一計算的js檔案必須要放在媒體查詢的css檔案前面,不然就會出現 htmlFontSize 一直都是100%的計算錯誤

1.html{font-size: 50px;} //這個一定寫
2.JS動態計算和密集的媒體查詢二選一