天天看点

关于移动端开发的一些笔记像素动态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页面的终端适配

继续阅读