移動端適配問題


主要要解決的適配問題有

1.  元素自適應問題

2. 文字大小和邊框問題

3. 高清圖問題

4. 1像素問題

5. 橫豎屏顯示問題

我們css中的1px,通常叫做css像素(虛擬像素),物理像素 與虛擬像素的比就稱為設備像素比(dpr)

現在現代瀏覽器都支持 window.devicePixelRatio

 

一.  元素自適應問題

通過rem解決,rem不僅可以設置字體大小,還可以設置塊的寬高,相比與@media,可以支持中間屏幕,且公用一套樣式,減少工作量

二.  文字大小

對於文字大小,如果沒有要求嚴格還原設計稿,就不要使用rem自動調整大小。原因是:

① 在大屏幕下希望看到更多的文字(使用rem,文字在所有屏幕上顯示的個數一樣,只是大小不一樣)

② 中文點陣最好在12px, 14px, 16px,使用rem無法避免13px這些

div {
    font-size: 12px; // 默認寫上dpr為1的fontSize
}
[data-dpr="2"] div {
    font-size: 24px;
}
[data-dpr="3"] div {
    font-size: 36px;
}

對於阿里的lib-flexible,是通過判斷dpr的值動態給body標簽添加font-size屬性;原理相似;后面會貼出我修改的源碼

三. 高清圖問題

1. 使用 srcset標簽WebKit最新特性srcset簡介

<img src="http://g.ald.alicdn.com/bao/uploaded/i1/TB1d6QqGpXXXXbKXXXXXXXXXXXX_!!0-item_pic.jpg_160x160q90.jpg" srcset="http://img01.taobaocdn.com/imgextra/i1/803091114/TB2XhAPaVXXXXXmXXXXXXXXXXXX_!!803091114.jpg 2x, http://gtms04.alicdn.com/tps/i4/TB1wDjWGXXXXXbtXVXX6Cwu2XXX-398-510.jpg_q75.jpg 3x">

2、使用js自帶的 Image 異步加載圖片

<img id="img" data-src1x="xxx@1x.jpg" data-src2x="xxx@2x.jpg" data-src3x="xxx@3x.jpg"/>

var dpr = window.devicePixelRatio;
if(dpr > 3){
    dpr = 3;
};

var imgSrc = $('#img').data('src'+dpr+'x');
var img = new Image();
img.src = imgSrc;
img.onload = function(imgObj){
    $('#img').remove().prepend(imgObj);//替換img對象
};

3. 背景圖片高清解決方法(對於dpr=2,1個css像素對應4個物理像素)

對於dpr=1,物理像素和css相同,圖片高清。但對於dpr=2,導致每個像素點實際上有4倍的普通像素點,反過來說,一個CSS像素點實際分成了四個,這樣就造成了顏色只能近似選取,於是,我們看上去就變得模糊了。所以使用2x的圖片就剛剛好。。

但對於dpr=1,如果使用2x的圖片,由於一個css像素對應4個物理像素可以選擇,這是就會縮小像素采樣(Downsampling)

①使用media來處理

/* 普通顯示屏(設備像素比例小於等於1)使用1倍的圖 */
.css{
    background-image: url(img_1x.png);
}

/* 高清顯示屏(設備像素比例大於等於2)使用2倍圖  */
@media only screen and (-webkit-min-device-pixel-ratio:2){
    .css{
        background-image: url(img_2x.png);
    }
}

/* 高清顯示屏(設備像素比例大於等於3)使用3倍圖  */
@media only screen and (-webkit-min-device-pixel-ratio:3){
    .css{
        background-image: url(img_3x.png);
    }
}

②使用image-set來處理

.css {
    background-image: url(1x.png); /*不支持image-set的情況下顯示*/
    background: -webkit-image-set(
            url(1x.png) 1x,/* 支持image-set的瀏覽器的[普通屏幕]下 */
            url(2x.png) 2x,/* 支持image-set的瀏覽器的[2倍Retina屏幕] */
            url(3x.png) 3x/* 支持image-set的瀏覽器的[3倍Retina屏幕] */
    );
}

3⃣️ 也是常用的方法

utils.js

const dpr = window.devicePixelRatio || 1
function getImageUrl(url){
     return url.replace(".", `@${dpr > 1 ? 2 : 1}x.`);  
}

4⃣️ icon采用svg的格式(矢量圖標)

四. 1px問題(retina,即視網膜屏幕)

 什么是 1像素問題 ? 我們說的1像素,就是指1CSS像素。問題就是設計師實際了一條線,本來是1像素,但是在有些設備上,用了橫豎都是3的物理像素(即:3x3=9像素)來顯示這1像素(即:dpr=3),導致在這些設備上,這條線看上去非常粗!

1. 使用css3的 scaleY(0.5) 來解決

不過這種方法通常是通過偽類來實現的,所以一個div只能實現兩條線,有四周都有的話要創建兩個DIV。且只能實現直線問題

.div:before {
  content: '';
  position: absolute;
  left: 0;
  top: 0;
  bottom: auto;
  right: auto;
  height: 1px;
  width: 100%;
  background-color: #c8c7cc;
  display: block;
  z-index: 15;
  -webkit-transform-origin: 50% 0%;
          transform-origin: 50% 0%;
}
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
  .div:before {
    -webkit-transform: scaleY(0.5);
            transform: scaleY(0.5);
  }
}
@media only screen and (-webkit-min-device-pixel-ratio: 3) {
  .div:before {
    -webkit-transform: scaleY(0.33);
            transform: scaleY(0.33);
  }
}

 對於移動端適配,我現在用下列代碼

(function flexible (window, document) {
    var docEl = document.documentElement;
    console.log(docEl);
    var dpr = window.devicePixelRatio || 1;

    if( 2 < dpr && dpr < 3){
        dpr = 2;
    }else if( dpr > 3 ) {
        dpr = 3;
    }
    docEl.setAttribute("data-dpr", dpr);
    // adjust body font size
    function setBodyFontSize () {
    if (document.body) {
          document.body.style.fontSize = (12 * dpr) + 'px';
    }
    else {
          document.addEventListener('DOMContentLoaded', setBodyFontSize);
    }
    }
    setBodyFontSize();

    // set 1rem = viewWidth / 10
    function setRemUnit () {
        var rem = docEl.clientWidth / 10;
        docEl.style.fontSize = rem + 'px';
    }

    setRemUnit();

    // reset rem unit on page resize
    window.addEventListener('resize', setRemUnit);
    window.addEventListener('pageshow', function (e) {
        if (e.persisted) {
              setRemUnit();
        }
    })
    console.log(dpr);
    // detect 0.5px supports
    if (dpr >= 2) {
        var fakeBody = document.createElement('body');
        var testElement = document.createElement('div');
        testElement.style.border = '.5px solid transparent';
        fakeBody.appendChild(testElement)
        docEl.appendChild(fakeBody);
        if (testElement.offsetHeight === 1) {
              docEl.classList.add('hairlines');//ios7以下,android等其他系統里,0.5px會被顯示為0px,是IOS8+,是的話則加上hairlines的類名
        }
        docEl.removeChild(fakeBody);

      }
}(window, document))

對於解決1px問題,有時直接通過js在meta標簽里改頁面縮放就能完美解決。。但是本人還是用不慣。

這種解決方案的原理就是:將頁面整體所縮小1/2,又將html根字體擴大了2倍。所以,對於頁面上使用rem的元素,等於沒有變化,但是使用px的元素,由於頁面縮小了1/2,所有元素尺寸就相當於縮小了1/2。對於上面的例子來說,1px就相當於0.5px了。

https://github.com/amfe/lib-flexible/tree/master(lib-flexible的第一版本)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM