• 可能你也看到过px,dp,dip,sp,设备独立像素、虚拟像素……这些单位或概念吧,如果你对它们很了解,那本篇对你可能就没什么用了,当然本文并不试图解释这些东西的意思,而是尽可能通过解释这些东西产生的原因,...

    可能你也看到过px,dp,dip,sp,设备独立像素、虚拟像素……这些单位或概念吧,如果你对它们很了解,那本篇对你可能就没什么用了,当然本文并不试图解释这些东西的意思,而是尽可能通过解释这些东西产生的原因,记录一下自己对这些东西的理解。

    虚拟像素

    最初的最初,一个px单位就够了,很简单纯洁啊,一个px就代表一个屏幕上的像素点。电脑的屏幕虽然尺寸也有差距,但是不大。一般开发网页可以把网页宽度设置成800,900或者1000px,然后居中,两边留白。大屏幕和小屏幕的网页效果基本一样,不同的是大屏幕网页两边的留白会大一点。
    后来,特别是智能手机的普及,用户的屏幕变得不再单一,宽度从300多px到4000多px,这个跨度就不算小了。
    当然,可能面对这个300-4000,首先想到的是

        @media (min-width: 768px){ ... }
    
        @media (min-width: 992px){ ... }
    
        @media (min-width: 1200){ ... }
    

    对这玩意不熟悉的同学可以先百度一下“@media”。

    下面假定没有dp、sp……那些单位,1px代表屏幕上的一个像素点。

    但是,有的屏幕(比如,老式的“大头机”宽1024x高768)的宽比手机屏幕还小(比如常见的宽1080x高1920),甚至现在很多笔记本都是1366宽x768高的,比手机屏幕也大不了多少,甚至如果手机横屏的话,比笔记本还宽且高。那么手机上看到的网页里的内容会很小很小。所以,@media这种方式,,,,,,,,gg。

    这时候,就有人提出了虚拟像素的概念,就是不管真实有多少像素点,手机屏幕的宽度,都用300-400左右的数来表示,比如1125x2436像素的iphoneX的虚拟像素是375x812,320x480像素的iphone3的虚拟像素还是320x480。
    移动端网页开发时,css里的1px实际上就是虚拟像素(pc端里的1px就是真实的1px)。也就是说,手机的屏幕都在300-400px之间,不需要管真实像素是1920x1080还是750x什么什么的了,对形状要求高的设置固定宽度,其他元素撑开。那么@media就可以正常工作了~

    在浏览器里按ctrl+shirft+i,然后ctrl+shirft+m,可以看到手机屏幕模拟器,可以选择不同的型号。这些不同型号的手机的宽高,用的就是虚拟像素这种单位。大都在300-400左右(比较宽的是平板,火狐浏览器里还有笔记本的屏,不在今天的讨论范围)。

    2倍屏,3倍屏

    可以看到模拟器里,iphone6和iphoneX都是宽375,但是苹果官网上iphone6的宽是750,iphoneX的宽度是1125,这就是2倍屏,3倍屏的意思或者说原因。

    虚拟像素的别名

    虚拟像素有很多别名。比如逻辑像素(相对于物理像素,物理像素就是真实像素);设备无关像素(毕竟宽1125的iphoneX和750的iphone6都是375);设备独立像素(device independent pixel,缩写dip、dp,android里的概念)

    站在历史的角度,用发展的眼光看问题。

    其他单位

    sp和pt

    sp(scale independent pixel 缩放无关像素或者缩放独立像素)和dp很像,也是android里的概念,不同的是,android设备允许用户调整系统文字的大小,而sp的大小会随系统文字大小的改变而改变。举一个不恰当的例子,在2倍屏、系统文字大小为“正常”时,1sp = 2px(这里的px是真实像素),那么当系统文字大小为“大”时,可能1sp = 2.5px。
    pt是长度单位point的缩写,1pt=1/72英寸。

    rem和em

    一直用em、rem,但是一直不知道em是什么单词的缩写还是什么,今天找了半天也还是没找到,知道的大佬请留个言,感谢。
    em和rem常用来表示字体大小,公式:1em = 父级元素的字体大小。比如浏览器里的字体大小一般默认为16px,那么如果不对font-size进行任何改变的话,那么1em = 16px。常见的应用场景是:你不想对某个字体设置固定大小,而想根据父级元素的字体大小设置大小,那么如果你想设置成比父级元素小一点可以设置成0.9em或者0.8em,当然这个因人而异,喜欢就用。
    rem是root em(可能是吧……)是相对于根元素的字体的大小。

    展开全文
  • 关于移动端分辨率和像素的基本知识: 屏幕 移动设备与PC设备最大的差异在于屏幕,这主要体现在屏幕尺寸和屏幕分辨率两个方面。 通常我们所指的屏幕尺寸,实际上指的是屏幕对角线的长度(一般用英寸来度量)如下图...

    关于移动端分辨率和像素的基本知识

    1. 屏幕
      移动设备与PC设备最大的差异在于屏幕,这主要体现在屏幕尺寸和屏幕分辨率两个方面。
      通常我们所指的屏幕尺寸,实际上指的是屏幕对角线的长度(一般用英寸来度量)如下图所示
      在这里插入图片描述
      而分辨率则一般用像素来度量 px,表示屏幕水平和垂直方向的像素数,例如1920*1080指的是屏幕垂直方向和水平方向分别有1920和1080个像素点而构成,如下图所示
      在这里插入图片描述

    2. 长度单位
      在Web开发中可以使用px(像素)、em、pt(点)、in(英寸)、cm(厘米)做为长度单位,我们最常用px(像素)做为长度单位。
      我们可以将上述的几种长度单位划分成相对长度单位和绝对长度单位。
      在这里插入图片描述
      如上图所示,iPhone3G/S和iPhone4/S的屏幕尺寸都为3.5英寸(in)但是屏幕分辨率却分别为480320px、960480px,由此我们可以得出英寸是一个绝对长度单位,而像素是一个相对长度单位(像素并没有固定的长度)。

    3. 像素密度
      DPI(Dots Per Inch)是印刷行业中用来表示打印机每英寸可以喷的墨汁点数,计算机显示设备从打印机中借鉴了DPI的概念,由于计算机显示设备中的最小单位不是墨汁点而是像素,所以用PPI(Pixels Per Inch)值来表示屏幕每英寸的像素数量,我们将PPI、DPI都称为像素密度,但PPI应用更广泛,DPI在Android设备比较常见。
      如下图所示,利用 勾股定理 我们可以计算得出PPI
      在这里插入图片描述
      PPI值的越大说明单位尺寸里所能容纳的像素数量就越多,所能展现画面的品质也就越精细,反之就越粗糙。
      Retina即视网膜屏幕,苹果注册的命名方式,意指具有较高PPI(大于320)的屏幕。
      思考:在屏幕尺寸(英寸)固定时,PPI和像素大小的关系?
      结论:屏幕尺寸固定时,当PPI 越大,像素的实际大小就会越小,当PPI越小,像素实际大小就越大。

    4. 设备独立像素
      随着技术发展,设备不断更新,出现了不同PPI的屏幕共存的状态(如iPhone3G/S为163PPI,iPhone4/S为326PPI),像素不再是统一的度量单位,这会造成同样尺寸的图像在不同PPI设备上的显示大小不一样。
      如下图,假设你设计了一个163163的蓝色方块,在PPI为163的屏幕上,那这个方块看起来正好就是11寸大小,在PPI为326的屏幕上,这个方块看起来就只有0.50.5寸大小了。
      在这里插入图片描述
      做为用户是不会关心这些细节的,他们只是希望在不同PPI的设备上看到的图像内容差不多大小,所以这时我们需要一个新的单位,这个新的单位能够保证图像内容在不同的PPI设备看上去大小应该差不多,这就是独立像素,在IOS设备上叫PT(Point),Android设备上叫DIP(Device independent Pixel)或DP。
      举例说明就是iPhone 3G(PPI为163)1dp = 1px,iPhone 4(PPI为326)1dp = 2px。
      在这里插入图片描述
      我们也不难发现,如果想要iPhone 3G/S和iPhone 4/S图像内容显示一致,可以把iPhone 4/S的尺寸放大一倍(它们是一个2倍(@2x)的关系),即在iPhone3G/S的上尺寸为44
      44px,在iPhone4/S上为8888px,我们要想实现这样的结果可以设置4444dp,这时在iPhone3G/S上代表4444px,在iPhone4/S上代表8888px,最终用可以看到的图像差不多大小。
      通过上面例子我们不难发现dp同px是有一个对应(比例)关系的,这个对应(比例)关系是操作系统确定并处理,目的是确保不同PPI屏幕所能显示的图像大小是一致的,通过window.devicePixelRatio可以获得该比例值。
      见代码示例1-1.html
      下图展示了iPhone不同型号间dp和px的比例关系
      在这里插入图片描述
      从上图我们得知dp(或pt)和px并不总是绝对的倍数关系(并不总能保证能够整除),而是window.devicePixelRatio ~= 物理像素/独立像素,然而这其中的细节我们不必关心,因为操作系统会自动帮我们处理好(保证1dp在不同的设备上看上去大小差不多)。

    5. 像素
      1、物理像素指的是屏幕渲染图像的最小单位,属于屏幕的物理属性,不可人为进行改变,其值大小决定了屏幕渲染图像的品质,我们以上所讨论的都指的是物理像素。
      // 获取屏幕的物理像素尺寸
      window.screen.width;
      window.screen.height;
      // 部分移动设备下获取会有错误,与移动开发无关,只需要了解
      2、CSS像素,与设备无关像素,指的是通过CSS进行网页布局时用到的单位,其默认值(PC端)是和物理像素保持一致的(1个单位的CSS像素等于1个单位的物理像素),但是我们可通缩放来改变其大小。
      见代码示例1-3.html
      我们通过调整浏览器的缩放比例可以直观的理解CSS像素与物理像素之前的对应关系,如下图所示:
      在这里插入图片描述
      我们需要理解的是物理像素和CSS像素的一个关系,1个物理像素并不总是等于一个CSS像素,通过调整浏览器缩放比例,可以有以上3种情况。

    展开全文
  • 虽说在在web app开发中,只需要掌握页面布局,页面适配,能够将页面完美在各种设备上展现。但是,为什么要这样做?...设备像素是指设备中使用的物理像素,又称硬件像素 css像素 css像素是指cs
    虽说在在web app开发中,只需要掌握页面布局,页面适配,能够将页面完美在各种设备上展现。但是,为什么要这样做?这样做原理是什么?这么优点是什么?深究下去,大家不一定很清晰。


    那么,咱们一起学习下~

    一、2种像素

    设备像素
    设备像素是指设备中使用的物理像素,又称硬件像素

    css像素
    css像素是指css样式到吗中使用的逻辑像素。如果在一个设备中,硬件像素数与css像素数相等,将不会产生任何问题。但是,由于视网膜设备的出现,这两者之间的差异变得越来越大。硬件像素数与css像素数成为两种截然不同的像素。

    例如在iphone 4设备屏幕中的物理像素是640px*960px,而css逻辑像素数为320*480px。因此,使用大约4个物理像素来显示一个css像素。

    针对图像来说,web应用程序开发者们的目标是在尽量保证页面性能的前提下显示高质量的图片。

    二、与像素相关的其他单位

    什么是设备像素比(device pixel ratio)?

    设备像素比是指设备像素与css像素之间的比例。当这个比率为1:1时,使用1个设备像素显示1个css像素。当这个比率为2:1时,使用4个设备像素显示1个css像素。当这个比率为3:1,使用9(3*3)个设备像素显示1个css像素。

    什么是像素密度?

    每英寸中多显示的像素数=ppi(pixels per inch)。在移动开发领域中,使用ppi来作为像素密度的单位。最近的移动设备中像素密度如下表所示。
    移动端开发--物理像素和逻辑像素 - angelinawu - angelinawu的博客
    像素密度与像素比之间的关系

    虽然设备像素密度值越高,即每英寸中所显示像素数越多,设备屏幕中图像越清晰。但是设备像素密度值与设备像素比之间并没有直接关系。例如,在Galaxy S IV设备中,设备像素密度为441ppi,设备像素比为2,在HTC One设备中,设备像素密度为468ppi,设备像素比为3。


    与设备像素比像素的dp像素与window.devicePixelRatio

    Android设备中 独立于设备像素密度的dp像素

    dp是创建Android应用程序时使用的一种独立与设备像素密度的像素单位。由于在160dpi(dots per inch:每英寸中显示的点数)的设备中,1px=1dp,因此在320dpi的设备中,1px=2dp,在480dpi的设备中,1px=3dp。

    请注意:这个dp与前文所述设备像素比是两码事。


    三、关于window.devicePixelRatio

    Wikipedia网页中记载了各种设备的设备像素比,本文并不进行具体描述。这里我们只介绍一下window.devicePixelRatio。

    在JavaScript脚本程序中,可以使用window,devicePixelRatio取得设备的设备像素比。

    window.devicePixelRatio的注意点

    另外,在使用window.devicePivelRatio的时候,有一下两点需要注意:

    1. 在Firefox浏览器与IE浏览器中不支持window.devicePixelRatio。
    2、在同一设备中的不同浏览器中的window.devicePixelRatio值有可能不同。

    例如,在720*1200px的Galaxy Nexus设备中,在Android浏览器与Chrome浏览器中的window.devicePixelRatio值是2,在Opera浏览器中的window.devicePixelRatio值为2.25.由于在Android浏览器与chrome浏览器中的css像素数为360px在Opera浏览器中的css像素数为320px所以设备像素比的计算方式如下所示:

    在Android浏览器与Chrome浏览器中

    720 / 360 = 2

    在Opera浏览器中

    720/320 = 2.25
    在iphone 5的Safari浏览器,Chrome浏览器与Opera浏览器中的设备像素比分别为2、2、1.

    四、使用媒体查询表达式

    为了在高分辨率设备中显示清晰的图像,可以使用某提查询表达式-webkit-device-pixel-ratio特性。接下来,我们首先对-webkit-device-pixel-ratio特性做一介绍,然后,介绍媒体查询表达式的resolution特性,最后,总结下如何为高分辨率设备使用媒体查询表达式。

    -webkit-device-pixel-ratio

    -webkit-device-pixel-ratio原本是针对苹果的视网膜设备进行开发时为了将设备像素转换成css像素时使用的一个媒体查询表达式特性,后来该特性在Android设备中得到了支持。 在Safari开发者说明中针对这一特性,有着如下所示的定义:

    "-webkit-device-pixel-ratio":苹果设备中使用的特殊比例:2代表视网膜屏幕,1代表标准屏幕。在Safari 4.0以上浏览器中支持。

    此处并没有对该比例进行详细说明,只说1代表标准屏幕,2代表视网膜屏幕。但是,在iphone 4中的device-pixel-ratio(设备像素比)为2,设备像素数为css像素数的2倍(640/320px),device-pixel-ratio=设备像素数/css像素数

    Android设备中的-webkit-device-pixel-ratio

    在Android设备开发者专用web网站中,针对-webkit-device-pixel-ratio有着如下所示的定义:
    “在Android浏览器与WebView浏览器中,支持针对特定像素密度创建样式时所使用的-webkit-device-pixel-ratio。可指定值为0.75、1与1.5,分别代表低像素密度屏幕、中像素密度屏幕和高屏幕屏幕”。

    展开全文
  • 移动端1px实线 描述:因为移动端设备分辨率高,所以H5中的1px到移动端上后,变粗了; 解决方法: 1.通过媒体查询判断出移动端设备 2.使用transform将1px实线缩放 此处使用的是stylus方案,如果项目中不支持stylus,...

    移动端1px实线

    描述:因为移动端设备分辨率高,所以H5中的1px到移动端上后,变粗了;
    解决方法:
    1.通过媒体查询判断出移动端设备
    2.使用transform将1px实线缩放
    此处使用的是stylus方案,如果项目中不支持stylus,则需要引入

    创建三个文件 (在一个文件下)

    1.base.styl 文件

    @media (-webkit-min-device-pixel-ratio: 1.5),(min-device-pixel-ratio: 1.5)
       .border-1px
        .border-all-1px
           &::after
              -webkit-transform: scaleY(0.3)
              transform: scaleY(0.3)
     
    @media (-webkit-min-device-pixel-ratio: 2),(min-device-pixel-ratio: 2)
       .border-1px
       .border-all-1px
           &::after
              -webkit-transform: scaleY(0.3)
              transform: scaleY(0.3)
    
    @media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3)
       .border-1px
       .border-all-1px
           &::after
              -webkit-transform: scaleY(0.3)
              transform: scaleY(0.3)
    
    

    2.index.styl

    @import "./mixin.styl";
    @import "./base.styl";
    

    3.mixin.styl

    
    .border-1px
      position : relative
      &:after
        display: block
        position: absolute
        left: 0
        bottom: 0
        border-top 1px solid #dfdddd
        width: 100%
        content: ''
    .border-all-1px
      position : relative
      &:after
        display: block
        position: absolute
        left: 0
        bottom: 0
        border 1px solid #dfdddd
        width: 100%
        content: ''
    

    引入

    // 移动端1px实线
    import './stylus/index.styl';  // 此处根据个人路劲填写
    

    调用

    <div class="border-1px"></div>
    

    如果是项目进行中引用,可能会引发一些样式变化,注意及时调整

    展开全文
  • 像素和dpr定义像素,又称画素,是图像显示的基本单位,译自英文“pixel”,pix 是英语单词 picture 的常用简写,加上英语单词“元素” element,就得到 pixel,故“像素”表示“图像元素”之意,有时亦被称为 pel...

    像素和dpr

    定义

    像素,又称画素,是图像显示的基本单位,译自英文“pixel”,pix 是英语单词 picture 的常用简写,加上英语单词“元素” element,就得到 pixel,故“像素”表示“图像元素”之意,有时亦被称为 pel(picture element)

    像素是网页布局的基础。一个像素就是计算机能够显示一种特定颜色的最小区域。当设备尺寸相同但像素变得更密集时,屏幕能显示的画面的过渡更细致,网站看起来更明快。

    ppi 是指屏幕上每英寸可以显示的像素点的数量,即屏幕像素密度

    分类

    像素分为两种:设备像素和 CSS 像素

    1. 设备像素(device independent pixels): 设备屏幕的物理像素,任何设备的物理像素的数量都是固定的
    2. CSS 像素(CSS pixels): 又称为逻辑像素,是为web开发者创造的,在 CSS 和 javascript 中使用的一个抽象的层

    CSS 声明和几乎所有的 javascript 属性都使用 CSS 像素,因此实际上从来用不上设备像素,唯一的例外是screen.width/height

    //我们通过CSSjavascript代码设置的像素都是逻辑像素
    width:300px;
    font-size:16px;
    

    缩放

    (设备像素→深蓝色背景,CSS 像素→半透明背景)

    在桌面端,css 的1个像素往往都是对应着电脑屏幕的1个物理像素。

    //一个 CSS 像素完全覆盖了一个设备像素

    image

    而在手机端,由于屏幕尺寸的限制,缩放是经常性的操作。

    //左图表示当用户进行缩小操作时,一个设备像素覆盖了多个 CSS 像素

    //右图表示当用户进行放大操作时,一个 CSS 像素覆盖了多个设备像素

    image image

    不论我们进行缩小或放大操作,元素设置的 CSS 像素(如width:300px)是始终不变的,而一个 CSS 像素对应多少个设备像素是根据当前的缩放比例来决定的

    DPR

    设备像素比 DPR (devicePixelRatio) 是默认缩放为100%的情况下,设备像素和 CSS 像素的比值

    DPR = 设备像素 / CSS像素(某一方向上)
    

    在早先的移动设备中,并没有 DPR 的概念。随着技术的发展,移动设备的屏幕像素密度越来越高。从 iphone4 开始,苹果公司推出了所谓的 retina 视网膜屏幕。之所以叫做视网膜屏幕,是因为屏幕的 PPI (屏幕像素密度)太高,人的视网膜无法分辨出屏幕上的像素点。iphone4 的分辨率提高了一倍,但屏幕尺寸却没有变化,这意味着同样大小的屏幕上,像素多了一倍,于是 DPR = 2

    CSS 像素对应着理想视口,其对应的javascript属性是screen.width/screen.height。设备像素比 DPR 对应的 javascript 属性是window.devicePixelRatio

    以 iphone5 为例,iphone5 的 CSS 像素为320px * 568px,DPR 是 2,所以其设备像素为640px * 1136px

    640(px) / 320(px)  = 2
    1136(px) / 568(px) = 2
    640(px)*1136(px) /  320(px)*568(px) = 4
    

    常用移动设备dpr

    IOS设备PPIDPR
    iPhone43262
    iPhone4s3262
    iPhone53262
    iPhone5s3262
    iPhone63262
    iPhone6s3262
    iPhone6 PLUS4413
    iPhone6s PLUS4413
    iPad --2
    iPad --3
    android尺寸dpr
    低清设备1
    -1.5
    -1.75
    -2
    mx2800*12802.5
    小米note720*12802.75
    --3
    三星note4-4
    .........
    .........

    总的来说,ios设备的dpr总体来说比较一致。

    解决方案

    1. 淘宝的移动端布局方案 Flexible

    /
        hotcss 可能有神奇的问题
    /
    !function() {
        var innerStyle = "@charset \"utf-8\";html{color:#000;background:#fff;overflow-y:scroll;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}html {outline:0;-webkit-text-size-adjust:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}html,body{font-family:sans-serif}body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td,hr,button,article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{margin:0;padding:0}input,select,textarea{font-size:100%}table{border-collapse:collapse;border-spacing:0}fieldset,img{border:0}abbr,acronym{border:0;font-variant:normal}del{text-decoration:line-through}address,caption,cite,code,dfn,em,th,var{font-style:normal;font-weight:500}ol,ul{list-style:none}caption,th{text-align:left}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:500}q:before,q:after{content:''}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}a:hover{text-decoration:underline}ins,a{text-decoration:none}",
            createStyle = document.createElement("style");
        if (document.getElementsByTagName("head")[0].appendChild(createStyle),
                createStyle.styleSheet)
            createStyle.styleSheet.disabled || (createStyle.styleSheet.cssText = innerStyle);
        else
            try {
                createStyle.innerHTML = innerStyle;
            } catch (ex) {
                createStyle.innerText = innerStyle;
            }
    }();
    ! function(window, nameSpace) {
        var timer, doc = window.document,
            docEl = doc.documentElement,
            metaEl = doc.querySelector('meta[name="viewport"]'),
            flexibleEl = doc.querySelector('meta[name="flexible"]'),
            dpr = 0,
            scale = 0,
            Flexible = nameSpace.flexible || (nameSpace.flexible = {});
            // Flexible 开创命名空间
        //刷新rem
        function refreshRem() {
            var width = docEl.getBoundingClientRect().width;
            //width / dpr > 540 && (width = 540  dpr);
            if(width / dpr > 540) {
                width = 540  dpr ;
            }
            var rootSize = width / 10;
            docEl.style.fontSize = rootSize + "px",
             Flexible.rem = window.rem = rootSize;
        }
        if (metaEl) {
           console.warn('将根据已有的meta标签来设置缩放比例');
           var match = metaEl.getAttribute('content').match(/initial-scale=([\d.]+)/);
           if (match) {
               scale = parseFloat(match[1]);
               dpr = parseInt(1 / scale);
           }
           //如果在meta标签中,我们手动配置了flexible,则使用里面的内容
        } else if (flexibleEl) {
           var content = flexibleEl.getAttribute('content');
           if (content) {
               var initialDpr = content.match(/initial-dpr=([\d.]+)/);
               var maximumDpr = content.match(/maximum-dpr=([\d.]+)/);
               if (initialDpr) {
                   dpr = parseFloat(initialDpr[1]);
                   scale = parseFloat((1 / dpr).toFixed(2));
               }
               if (maximumDpr) {
                   dpr = parseFloat(maximumDpr[1]);
                   scale = parseFloat((1 / dpr).toFixed(2));
               }
           }
        }
        if (!dpr && !scale) {
            var isAndroid = window.navigator.appVersion.match(/android/gi);
            var isIPhone = window.navigator.appVersion.match(/iphone/gi);
            //devicePixelRatio这个属性是可以获取到设备的dpr
            var devicePixelRatio = window.devicePixelRatio;
            if (isIPhone) {
                if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
                    dpr = 3;
                } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
                    dpr = 2;
                } else {
                    dpr = 1;
                }
            } else {
                dpr = 1;
            }
            scale = 1 / dpr;
        }
        if (docEl.setAttribute("data-dpr", dpr), !metaEl)
            if (metaEl = doc.createElement("meta"),
                    metaEl.setAttribute("name", "viewport"),            //j = scale            //j = scale              //j = scale
                    metaEl.setAttribute("content", "initial-scale=" + scale + ", maximum-scale=" + scale + ", minimum-scale=" + scale + ", user-scalable=no"),
                    docEl.firstElementChild)
                docEl.firstElementChild.appendChild(metaEl);
            else {
                var createDiv = doc.createElement("div");
                createDiv.appendChild(metaEl),
                    doc.write(createDiv.innerHTML)
                }
        window.addEventListener("resize", function() {
                    clearTimeout(timer),
                        timer = setTimeout(refreshRem, 300);
            }, !1),
                window.addEventListener("pageshow", function(a) {
                a.persisted && (clearTimeout(timer),
                    timer = setTimeout(refreshRem, 300))
            }, !1),
            "complete" === doc.readyState ? doc.body.style.fontSize = 17  dpr + "px" : doc.addEventListener("DOMContentLoaded", function() {
                doc.body.style.fontSize = 17  dpr + "px"
            }, !1),
            refreshRem(),
            Flexible.dpr = window.dpr = dpr,
            Flexible.refreshRem = refreshRem,
            Flexible.rem2px = function(a) {
                var pxValue = parseFloat(a)  this.rem;
                return "string" == typeof a && a.match(/rem$/) && (pxValue += "px"), pxValue ;
            },
            Flexible.px2rem = function(a) {
                var remValue = parseFloat(a) / this.rem;
                return "string" == typeof a && a.match(/px$/) && (remValue += "rem"), remValue ;
            }
    }(window, window.lib || (window.lib = {}));
    

    核心方法如下:

    if (metaEl) {
        console.warn('将根据已有的meta标签来设置缩放比例');
        var match = metaEl.getAttribute('content').match(/initial-scale=([\d.]+)/);
        if (match) {
            scale = parseFloat(match[1]);
            dpr = parseInt(1 / scale);
        }
        //如果在meta标签中,我们手动配置了flexible,则使用里面的内容
    } else if (flexibleEl) {
        var content = flexibleEl.getAttribute('content');
        if (content) {
            var initialDpr = content.match(/initial-dpr=([\d.]+)/);
            var maximumDpr = content.match(/maximum-dpr=([\d.]+)/);
            if (initialDpr) {
                dpr = parseFloat(initialDpr[1]);
               scale = parseFloat((1 / dpr).toFixed(2));
           }
           if (maximumDpr) {
               dpr = parseFloat(maximumDpr[1]);
               scale = parseFloat((1 / dpr).toFixed(2));
           }
       }
    }
    
    if (!dpr && !scale) {
        var isAndroid = window.navigator.appVersion.match(/android/gi);
        var isIPhone = window.navigator.appVersion.match(/iphone/gi);
        //devicePixelRatio这个属性是可以获取到设备的dpr
        var devicePixelRatio = window.devicePixelRatio;
        if (isIPhone) {
            if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
                dpr = 3;
            } else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
                dpr = 2;
            } else {
                dpr = 1;
            }
        } else {
            dpr = 1;
            // 其他设备仍旧使用1倍的方案
        }
        scale = 1 / dpr;
    }
    

    这里只对ios作了处理,android 仍采用了1倍的布局方案。

    2. 另一种方案 hotcss.js

    (function(window, document) {
        'use strict';
        //hotcss开辟个命名空间,别问我为什么,我要给你准备你会用到的方法,免得用到的时候还要自己写。
        var hotcss = {};
        (function() {
            //根据devicePixelRatio自定计算scale
            //可以有效解决移动端1px这个世纪难题。
            var viewportEl = document.querySelector('meta[name="viewport"]'),
                hotcssEl = document.querySelector('meta[name="hotcss"]'),
                dpr = window.devicePixelRatio || 1,
                maxWidth = 540,
                designWidth = 0;
            dpr = dpr >= 3 ? 3 : (dpr >= 2 ? 2 : 1);
            //允许通过自定义namehotcssmeta头,通过initial-dpr来强制定义页面缩放
            if (hotcssEl) {
                var hotcssCon = hotcssEl.getAttribute('content');
                if (hotcssCon) {
                    var initialDprMatch = hotcssCon.match(/initial-dpr=([\d.]+)/);
                    if (initialDprMatch) {
                        dpr = parseFloat(initialDprMatch[1]);
                    }
                    var maxWidthMatch = hotcssCon.match(/max-width=([\d.]+)/);
                    if (maxWidthMatch) {
                        maxWidth = parseFloat(maxWidthMatch[1]);
                    }
                    var designWidthMatch = hotcssCon.match(/design-width=([\d.]+)/);
                    if (designWidthMatch) {
                        designWidth = parseFloat(designWidthMatch[1]);
                    }
                }
            }
            document.documentElement.setAttribute('data-dpr', dpr);
            hotcss.dpr = dpr;
            document.documentElement.setAttribute('max-width', maxWidth);
            hotcss.maxWidth = maxWidth;
            if (designWidth) {
                document.documentElement.setAttribute('design-width', designWidth);
                hotcss.designWidth = designWidth;
            }
            var scale = 1 / dpr,
                content = 'width=device-width, initial-scale=' + scale + ', minimum-scale=' + scale + ', maximum-scale=' + scale + ', user-scalable=no';
            if (viewportEl) {
                viewportEl.setAttribute('content', content);
            } else {
                viewportEl = document.createElement('meta');
                viewportEl.setAttribute('name', 'viewport');
                viewportEl.setAttribute('content', content);
                document.head.appendChild(viewportEl);
            }
        })();
        hotcss.px2rem = function(px, designWidth) {
            //预判你将会在JS中用到尺寸,特提供一个方法助你在JS中将px转为rem。就是这么贴心。
            if (!designWidth) {
                //如果你在JS中大量用到此方法,建议直接定义 hotcss.designWidth 来定义设计图尺寸;
                //否则可以在第二个参数告诉我你的设计图是多大。
                designWidth = parseInt(hotcss.designWidth, 10);
            }
            return parseInt(px, 10)  320 / designWidth / 20;
        }
        hotcss.rem2px = function(rem, designWidth) {
            //新增一个rem2px的方法。用法和px2rem一致。
            if (!designWidth) {
                designWidth = parseInt(hotcss.designWidth, 10);
            }
            //rem可能为小数,这里不再做处理了
            return rem  20  designWidth / 320;
        }
        hotcss.mresize = function() {
            //对,这个就是核心方法了,给HTML设置font-size
            var innerWidth = document.documentElement.getBoundingClientRect().width || window.innerWidth;
            if (hotcss.maxWidth && (innerWidth / hotcss.dpr > hotcss.maxWidth)) {
                innerWidth = hotcss.maxWidth  hotcss.dpr;
            }
            if (!innerWidth) {
                return false;
            }
            document.documentElement.style.fontSize = (innerWidth * 20 / 320) + 'px';
            hotcss.callback && hotcss.callback();
        };
        hotcss.mresize();
        //直接调用一次
        window.addEventListener('resize', function() {
            clearTimeout(hotcss.tid);
            hotcss.tid = setTimeout(hotcss.mresize, 33);
        }, false);
        //绑定resize的时候调用
        window.addEventListener('load', hotcss.mresize, false);
        //防止不明原因的bugload之后再调用一次。
        setTimeout(function() {
            hotcss.mresize();
            //防止某些机型怪异现象,异步再调用一次
        }, 333)
        window.hotcss = hotcss;
        //命名空间暴露给你,控制权交给你,想怎么调怎么调。
    })(window, document);
    

    里面有这样简单粗暴的设置:

    dpr = dpr >= 3 ? 3 : ( dpr >=2 ? 2 : 1 );
    

    3. 前端开发博客的方案

    
    <span style="font-family: Arial, Helvetica, sans-serif;">动态写dpr和根元素的fontsize  </span> 
    
    !function(x) {  
        function w() {  
            var a = r.getBoundingClientRect().width;  
            a / v > 540 && (a = 540 * v), x.rem = a / 16, r.style.fontSize = x.rem + "px"  
        }  
        var v, u, t, s = x.document, r = s.documentElement, q = s.querySelector('meta[name="viewport"]');  
        if (q) {  
            console.warn("将根据已有的meta标签来设置缩放比例");  
            var o = q.getAttribute("content").match(/initial\-scale=(["]?)([\d\.]+)\1?/);  
            o && (u = parseFloat(o[2]), v = parseInt(1 / u))  
        }  
        if (!v && !u) {  
            var n = (x.navigator.appVersion.match(/android/gi), x.navigator.appVersion.match(/iphone/gi)), v = x.devicePixelRatio;  
            v = n ? v >= 3 ? 3 : v >= 2 ? 2 : 1 : 1, u = 1 / v  
        }  
        if (r.setAttribute("data-dpr", v), !q) {  
            if (q = s.createElement("meta"), q.setAttribute("name", "viewport"), q.setAttribute("content", "initial-scale=" + u + ", maximum-scale=" + u + ", minimum-scale=" + u + ", user-scalable=no"), r.firstElementChild) {  
                r.firstElementChild.appendChild(q)  
            } else {  
                var m = s.createElement("div");  
                m.appendChild(q), s.write(m.innerHTML)  
            }  
        }  
        x.dpr = v, x.addEventListener("resize", function() {  
            clearTimeout(t), t = setTimeout(w, 300)  
        }, !1), x.addEventListener("pageshow", function(b) {  
            b.persisted && (clearTimeout(t), t = setTimeout(w, 300))  
        }, !1), "complete" === s.readyState ? s.body.style.fontSize = 12 * v + "px" : s.addEventListener("DOMContentLoaded", function() {  
            s.body.style.fontSize = 12 * v + "px"  
        }, !1), w()  
    }(window); 
    

    4. 耿旭亮的方案

    直接存为一个 viewport.js 文件,在所有js中最先引入该文件

    !function(win, lib) {
        var timer,
            doc     = win.document,
            docElem = doc.documentElement,
    
            vpMeta   = doc.querySelector('meta[name="viewport"]'),
            flexMeta = doc.querySelector('meta[name="flexible"]'),
     
            dpr   = 0,
            scale = 0,
     
            flexible = lib.flexible || (lib.flexible = {});
     
        // 设置了 viewport meta
        if (vpMeta) {
     
            console.warn("将根据已有的meta标签来设置缩放比例");
            var initial = vpMeta.getAttribute("content").match(/initial\-scale=([\d\.]+)/);
     
            if (initial) {
                scale = parseFloat(initial[1]); // 已设置的 initialScale
                dpr = parseInt(1 / scale);      // 设备像素比 devicePixelRatio
            }
     
        }
        // 设置了 flexible Meta
        else if (flexMeta) {
            var flexMetaContent = flexMeta.getAttribute("content");
            if (flexMetaContent) {
     
                var initial = flexMetaContent.match(/initial\-dpr=([\d\.]+)/),
                    maximum = flexMetaContent.match(/maximum\-dpr=([\d\.]+)/);
     
                if (initial) {
                    dpr = parseFloat(initial[1]);
                    scale = parseFloat((1 / dpr).toFixed(2));
                }
     
                if (maximum) {
                    dpr = parseFloat(maximum[1]);
                    scale = parseFloat((1 / dpr).toFixed(2));
                }
            }
        }
     
        // viewport  flexible
        // meta 均未设置
        if (!dpr && !scale) {
            // QST
            // 这里的 第一句有什么用 ?
            //  Android 有毛关系 ?
            var u = (win.navigator.appVersion.match(/android/gi), win.navigator.appVersion.match(/iphone/gi)),
                _dpr = win.devicePixelRatio;
     
            // 所以这里似乎是将所有 Android 设备都设置为 1 
            dpr = u ? ( (_dpr >= 3 && (!dpr || dpr >= 3))
                            ? 3
                            : (_dpr >= 2 && (!dpr || dpr >= 2))
                                ? 2
                                : 1
                      )
                    : 1;
     
            scale = 1 / dpr;
        }
     
        docElem.setAttribute("data-dpr", dpr);
     
        // 插入 viewport meta
        if (!vpMeta) {
            vpMeta = doc.createElement("meta");
             
            vpMeta.setAttribute("name", "viewport");
            vpMeta.setAttribute("content",
                "initial-scale=" + scale + ", maximum-scale=" + scale + ", minimum-scale=" + scale + ", user-scalable=no");
     
            if (docElem.firstElementChild) {
                docElem.firstElementChild.appendChild(vpMeta)
            } else {
                var div = doc.createElement("div");
                div.appendChild(vpMeta);
                doc.write(div.innerHTML);
            }
        }
     
        function setFontSize() {
            var winWidth = docElem.getBoundingClientRect().width;
     
            if (winWidth / dpr > 540) {
                (winWidth = 540 * dpr);
            }
     
            // 根节点 fontSize 根据宽度决定
            var baseSize = winWidth / 10;
     
            docElem.style.fontSize = baseSize + "px";
            flexible.rem = win.rem = baseSize;
        }
     
        // 调整窗口时重置
        win.addEventListener("resize", function() {
            clearTimeout(timer);
            timer = setTimeout(setFontSize, 300);
        }, false);
     
         
        // orientationchange 时也需要重算下吧
        win.addEventListener("orientationchange", function() {
            clearTimeout(timer);
            timer = setTimeout(setFontSize, 300);
        }, false);
     
     
        // pageshow
        // keyword: 倒退 缓存相关
        win.addEventListener("pageshow", function(e) {
            if (e.persisted) {
                clearTimeout(timer);
                timer = setTimeout(setFontSize, 300);
            }
        }, false);
     
        // 设置基准字体
        if ("complete" === doc.readyState) {
            doc.body.style.fontSize = 12 * dpr + "px";
        } else {
            doc.addEventListener("DOMContentLoaded", function() {
                doc.body.style.fontSize = 12 * dpr + "px";
            }, false);
        }
      
        setFontSize();
     
        flexible.dpr = win.dpr = dpr;
     
        flexible.refreshRem = setFontSize;
     
        flexible.rem2px = function(d) {
            var c = parseFloat(d) * this.rem;
            if ("string" == typeof d && d.match(/rem$/)) {
                c += "px";
            }
            return c;
        };
     
        flexible.px2rem = function(d) {
            var c = parseFloat(d) / this.rem;
             
            if ("string" == typeof d && d.match(/px$/)) {
                c += "rem";
            }
            return c;
        }
    }(window, window.lib || (window.lib = {}));
    展开全文
  • 一直以来,本人对移动端分辨率、像素等概念傻傻分不清,特查阅多位牛人博客后总结如下要点,以便日后查看。 文档来源http://weizhifeng.net/you-should-know-about-dpi.html ...
  • 移动端0.5像素细线

    2019-03-19 14:35:18
    方法一 .line { height: 0.5px; background-color: gray; } 优点:设置简单,ios上实用 缺点:安卓不兼容 方法二 .line { height: 1px; background-color: gray; transform: scaleY(0.5);......
  • 1像素: 步骤一:新建base.styl的文件, 步骤二:新建index.styl,把base.styl的文件放在里面 步骤三:在main.js引入即可全局使用 为什么需要一像素,看下边: DIPs指设备独立像素(DPI指每英寸点的个数) 非...
  • 在做移动端网页开发时,首先要搞清楚三种viewport和三种像素,只有明白了这些概念,才能更好地开发出适配不同分辨率设备的网页。 但参阅的博客越多,对这些概念越是混乱,同样的一个概念,在一篇博客中是这种说法,...
  • 原来一直没在意,源于自己根本不是像素眼…… 今天仔细瞅了瞅原生实现的边框和CSS设置的边框,确实差距不小……上图是原生实现,下图是 CSS 边框,手机上对比更加明显 然后,如何解决呢?搜遍整个谷歌,发现好多...
  • 最近工作任务主要是移动端内嵌H5页面,一次与原生进行像素交互下,发现了这个天坑,再次做个记录???? 天坑如下:  H5页面中的“像素”与移动端设备的“像素”系统不一致,对于刚接触这块的我,曾经几时在还没有...
  • 最近在做移动端的开发,深入了解了下移动端适配的一些问题,加上自己的理解,记录下来,写一个小的系列博客,与大家分享。所有的问题,就开始从像素说起吧~ 像素是一个经常提到的概念,写CSS的人都经常会用到px作为...
  • (2)css像素/逻辑像素:指的是开发的像素,CSS 中的像素是一个相对值,不是绝对值,因此1px 的 CSS 像素并不一定等于 1px 的物理像素 (3)设备像素比dpr:物理像素除以css像素 物理设备根据某种规则,决定该采用几...
  • =======================...最简单的基于FFmpeg的移动端例子:Android HelloWorld 最简单的基于FFmpeg的移动端例子:Android 视频解码器 最简单的基于FFmpeg的移动端例子:Android 视频解码器-单个库版 最简单的基于
  • 其中涉及几个重要概念是dip (与设备无关的像素设备逻辑像素)和CSS 像素之间的关系。这里首先了解以下几个概念。 一,视口 1,layout viewport(布局视口)  一般移动设备的浏览器都默认设置了一个视口 元标签...
  • rom版本的性能测试 一般关注功耗(不过 rom 版本的功耗测试跟应用的功耗测试会有所差异,当然只是用例设计方面的差异,工具仍然采用安捷伦电源仪进行) 应用的性能测试 包括很多测试项,如启动时间、内存、CPU...
  • 一直以来,本人对移动端分辨率、像素等概念傻傻分不清,特查阅多位牛人博客后总结如下要点,以便日后查看。 文档来源http://weizhifeng.net/you-should-know-about-dpi.html ...
  • 博主一开始学android的时候,对像素单位不知其所以然,只知一根筋的填数字,结果在模拟器上跑好好的界面,拿到真机上就显示得东倒西歪,害得自己使劲的找bug,这都是没打好基础的缘故呀。所以一开始就把像素这种基础...
  • 移动端像素的深究

    2016-09-21 23:19:55
    看了很多的文章,很多链接不记得了所以特意...在手机上,手机的像素是欺骗我们的眼睛的,主要分为  视觉视口 布局视口 理想市口  想要理解这几个之间的关系首先应该明白像素的一些知识。 1 设备的实际像素  这个就是
1 2 3 4 5 ... 20
收藏数 6,148
精华内容 2,459