天天看點

關于移動端開發的一些筆記像素動态rem移動端1px問題flexible.js

關于一些基本概念如裝置像素,css像素,參考

  • 移動端适配方案(上)
  • CSS像素、實體像素、邏輯像素、裝置像素比、PPI、Viewport

像素

關于移動端開發的一些筆記像素動态rem移動端1px問題flexible.js

上圖的pt和px互換才正确,reader @2x 指裝置像素比

meta裡面設定width=device-width,這個device-width就是裝置獨立像素。

在chrome裡 看到的375*667是裝置獨立像素

關于移動端開發的一些筆記像素動态rem移動端1px問題flexible.js

設計師給的是640px寬的設計稿是根據裝置像素(device pixel,實體像素)為機關制作的設計稿;而前端工程師參照相關的裝置像素比來進行換算,比如根據iPhone5出稿的設計稿的中有一個width:100px,height:200px的按鈕,那麼前端工程師在編碼web頁面時應該寫width:50px,height:100px。他們之間的換算比例是根據裝置像素比來計算的。

<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">

,iphone5的css像素是320X568,當

<meta name="viewport" content="width=device-width, initial-scale=0.5, minimum-scale=0.5, maximum-scale=0.5, user-scalable=no">

,css像素變成640X1136(如下圖),這是因為當scale=1,1個css像素對應2個實體像素,而iphone5的實體像素是640X1136,當scale=0.5,1個css像素對應1個實體像素,css像素必須變成640X1136才能剛好完全對應所有實體像素,需要注意的是當scale=1,你用css寫div height:50px;在開發者工具inspect div,确實高50px,變成scale=0.5,在開發者工具看div的height還是50px

關于移動端開發的一些筆記像素動态rem移動端1px問題flexible.js

動态rem

rem這個機關代表根元素的 font-size 大小,例如 <html> 元素的font-size為16px,則1rem=16px

手機有很多不同分辨率,如下圖,如果用響應式,要做3套css,如果隻想做1套css适應不同手機,方法是用百分比布局或整體縮放

關于移動端開發的一些筆記像素動态rem移動端1px問題flexible.js

百分比布局:

關于移動端開發的一些筆記像素動态rem移動端1px問題flexible.js

缺點是高度不能确定,不能實作例如寬高2:1,例如.child {height:20%} 是沒用的

整體縮放:

關于移動端開發的一些筆記像素動态rem移動端1px問題flexible.js

在解決這個問題上vw是最好的,因為vw和裝置寬度有關,1vw=視口寬度的 1/100,但相容性差

另外的方法就是動态rem,動态rem的簡單實作:https://jsbin.com/zoxizor/1/e...

  • 在 SCSS 裡使用 PX2REM :

在 scss 檔案裡添加

@function px( $px ){
  @return $px/$designWidth*10 + rem;
}
$designWidth : 640; // 640 是設計稿的寬度,


.child{
  width: px(320);  //5rem
  height: px(160);
  margin: px(40) px(40);
  border: 1px solid red;
  float: left;
  font-size: 1.2em;
}
           

即可實作 px 自動變 rem

移動端1px問題

以 dpr=2 為例:

你拿到一張标準的基于 iphone6 的設計稿(750px)

你看到它設計的一個 border寬度是 1px

那麼border的其實是 border: 0.5px solid #000;

但問題是在iOS 7 和之前版本,OS X Mavericks 及以前版本,還有 Android 裝置上浏覽器可能不認識0.5px的邊框,将會把它解釋成0px,沒有邊框。是以網上有很多其他的實作1px邊框的方法

而所謂的1px變粗請看 javascript - 1px邊框在移動端變粗問題産生的原理 , 移動端高清、多屏适配方案

設計稿上有1像素邊框,當你面對不同的螢幕時你希望它的行為是怎樣的?設計師希望在不同dpr的螢幕上這條線都是1實體像素。

下面flexible.js的部分代碼可以實作,

if (!dpr && !scale) {
        var isAndroid = win.navigator.appVersion.match(/android/gi);
        var isIPhone = win.navigator.appVersion.match(/iphone/gi);
        var devicePixelRatio = win.devicePixelRatio;
        if (isIPhone) {
            // iOS下,對于2和3的屏,用2倍的方案,其餘的用1倍方案
            if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
                dpr = 3;
            } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
                dpr = 2;
            } else {
                dpr = 1;
            }
        } else {
            // 其他裝置下,仍舊使用1倍的方案
            dpr = 1;
        }
        scale = 1 / dpr;
    }

    if (!metaEl) {
        metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
           

當直接寫

<meta name="viewport" content="initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">

,且dpr=2,border:1px,渲染出來是2px實體像素

<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">

,此時頁面被縮小50%,border:1px渲染出來是1px實體像素

flexible.js

為了解決1px邊框問題,flexible.js根據dpr對頁面縮放


    if (!dpr && !scale) {
        var isAndroid = win.navigator.appVersion.match(/android/gi);
        var isIPhone = win.navigator.appVersion.match(/iphone/gi);
        var devicePixelRatio = win.devicePixelRatio;
        if (isIPhone) {
            // iOS下,對于2和3的屏,用2倍的方案,其餘的用1倍方案
            if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {                
                dpr = 3;
            } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
                dpr = 2;
            } else {
                dpr = 1;
            }
        } else {
            // 其他裝置下,仍舊使用1倍的方案
            dpr = 1;
        }
        scale = 1 / dpr;
    }

    if (!metaEl) {
        metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');

    }
           

導緻字型font-size也要做相應調整:

.a{
  font-size:12px;
}
[data-dpr="2"] .a{
  font-size: 24px;
}
[data-dpr="3"] .a{
  font-size: 36px;
}
           

設計師原本的要求是這樣的:任何手機螢幕上字型大小都要統一

dpr=2,根據源碼, scale=0.5,是以1個css像素對應1個實體像素,font-size=24px,對應24個實體像素,而dpr=1時font-size=12px,對應12個實體像素,根據下圖,dpr=1的普通屏的1個實體像素寬,實體尺寸上等于dpr=2的retina屏的2個實體像素寬,是以任何手機螢幕上字型的實體尺寸大小一樣

關于移動端開發的一些筆記像素動态rem移動端1px問題flexible.js
  • 其他
if(document.body.ontouchstart !== undefined){}
      // 在pc上document.body.ontouchstart是undefined,表明不支援該事件,而在觸屏裝置上是null,支援該事件


  var x = event.touches[0].clientX  //touch點的x坐标
      // 因為手機支援多點觸控,是以關于touch的資訊都放在一個數組裡,touches[0]表示一點觸控,tounch[1]表示另外一點觸控

而在pc上用 var x = event.clientX 擷取滑鼠點選的x坐标
           

手機上沒有hover事件,resize事件

更多資料:

  • 淘寶flexiblejs用rem,為什麼還要縮放viewport? - 知乎
  • 如何在Vue項目中使用vw實作移動端适配
  • 移動端适配方案(下)
  • 再聊移動端頁面的适配
  • 使用Flexible實作手淘H5頁面的終端适配

繼續閱讀