本文说的devicePixelRatio指的是window.devicePixelRatio
,WebKit浏览器及Opera支持这个属性。
定义
Dips被用来向media query宽/高、meta视口(viewport)device-width传递设备信息。以Retina和非Retina设备之间的差异为例来说明直观一些。window.devicePixelRatio
指的是设备物理像素和设备独立像素(device-independent pixels, dips)的比例 on the device.window.devicePixelRatio
= 物理像素 / 设备独立像素(dips)
非Retina iPhone纵向的物理分辨率宽为320px,使用<meta name="viewport" content="width=device-width">
可以将布局视口设置为320px, 页面自然地适应屏幕。也就是说,非Retina iPhone的物理像素和设备独立像素都是320,因此<window.devicePixelRatio>
等于1。
Retina iPhone物理像素宽度为640,但是网站视口宽度不会变成640px,仍然是320——iPhone的最佳阅读尺寸。因此Retina iPhone的window.devicePixelRatio
等于2。
浏览器支持
大多数浏览器都能支持window.devicePixelRatio
属性,下面是不支持的浏览器列表:
- IE及Firefox完全不支持(经测试,Firefox 19已经支持,从那个版本开始支持未知;IE 10桌面版仍然不支持)
- Opera桌面版在Retina设备上返回1,实际上应该是2(PPK没有说是哪个版本的Opera,没有Retina Mac暂无法测试)
- Opera Mobile 10不支持,但12正确支持
- UC总是返回1,传递给UC的viewport属性很令人困惑
- 最近的Chrome才支持这一属性,Chrome 19错误返回1,Chrome 22正确返回2
- MeeGo WebKit (Nokia N9/N950) 有点恶心的问题:应用meta viewport后值会从1变到1.5
不过,这些浏览器目前多数都运行在<window.devicePixelRatio>
为1的设备上,以后在Retina设备上就可能出现问题。
不同设备的devicePixelRatio
PPK创建了一个测试页面,用来显示访问者的devicePixelRatio。目前绝大多数桌面电脑和笔记本的devicePixelRatio都是1,Retina笔记本在Safari、Chrome 22及Opera中返回2,IE和Firefox返回undefined。iOS
对iOS设备来说,非retina屏幕devicePixelRatio为1,retina屏幕为2。因为虽然实际像素成倍增加,但为了不破坏为320px宽的iPhone精心设计的网页,浏览器仍然将viewport中的device-width识别为320px,即dips仍为320px, 640/320 = 2。iOS平台相对简单,devicePixelRatio只有1和2这两个值。绝大多数其他平台的设备物理像素等于dips,所以也很简单,devicePixelRatio
为1。
Android
事实上Google Nexus One是最早使用dips的设备,甚至早于iPhone。Galaxy Nexus 和 Galaxy Note 也采用了类似retina的显示技术。- Nexus One物理分辨率480x800, 但Android WebKit开发团队认为竖屏模式320px宽度最适合网页浏览,因此dips仍设为320px,
devicePixelRatio
为 480/320 = 1.5。在这款手机上,Opera Mobile做了相同的处理,devicePixelRatio
同样是 1.5。 (顺便提一下,BlackBerry Torch 9810 搭载 OS7,物理分辨率同为480,但BlackBerry WebKit团队将devicePixelRatio
设为1。实际使用来看,设置成1.5应该好一些,480px宽的页面在Torch上看起来太费劲了。) - Galaxy Nexus物理分辨率为720x1200,Android团队将dips宽度提升为360px,
devicePixelRatio
720/360 = 2。Chrome、QQ浏览器也做了相同处理。但是Opera有些差异,dips宽仍为,320px,devicePixelRatio
of 720/320 = 2.25。 - Galaxy Note,物理分辨率800x1200,Android WebKit、Chrome、 QQ都为2(即dips宽为400px);Opera为2.25,即dips宽为 356px。
与其他属性的关系
devicePixelRatio
、物理分辨率、dips之间仅仅是单纯的数学计算,知道其中两个就可以算出第三个。但是如何获得dips宽度或者物理分辨率宽度呢?
获取dips宽度很简单:页面设置<meta name="viewport" content="width=device-width">
,获取document.documentElement.clientWidth
,绝大多数浏览器返回布局视口的宽度,等于dips宽度。(兼容列表)
如果无法使用上面的方法,就只能用screen.width了。
不同浏览器返回的值不同:
- Retina iOS设备上,
screen.width
返回dips宽,如retina和非retina iPad竖模式都返回768 - 在上面的三个Android设备中,
screen.width
返回物理分辨率宽度,所有浏览器都返回一样的值
其他平台上的浏览器如何呢?由于条件限制,只能在部分设备上测试。Nokia Lumia Windows Phone上的IE9和android一样,screen.width
返回物理分辨率,但是不支持devicePixelRatio
,无法做更全面的测试。
对于移动客户端上,可以总结为:
devicePixelRatio
在大多浏览器上都是可靠的。- iOS上,
devicePixelRatio
xscreen.width
= 物理分辨率。 - 在 Android 和 Windows Phone设备上,
screen.width
/devicePixelRatio
= dips。
Retina MacBook
Retina MacBook的devicePixelRatio
应该为2,但实际情况可能比想象中复杂,因为可以调整分辨率。关键是分辨率改变后,devicePixelRatio
保持不变。
Retina MacBook 是2800x1800物理分辨率为,显示分辨率为1400x900,所以devicePixelRatio
为2。但是将分辨率调为1920x1200之后, devicePixelRatio
还是 2。严格来说这是错误的,应该为1.5。但无论如何,Apple将devicePixelRatio
标准统一为1和2两个值对开发者还是有利的:监测到2,则提供为retina优化图片;如果为1,提供普通图片。
为Retina设备提供高分辨率图片将加重Web数据传输负担,特别是通过移动网络,但出于商业竞争考虑,很多公司还是会这样做。
内容来源: