如何获取CSS像素/设备像素比?

49

我想找到CSS像素和设备像素之间的比例。

编辑:我应该意识到这只是缩放级别。我已经在标准参考文献中添加了一个答案,讲述了缩放级别。

CSS像素是我们几乎用于所有内容的单位--它是element.style.width、element.clientWidth、element.offsetWidth等的含义。设备像素是浏览器实际绘制的像素。一些属性是以设备像素为单位进行测量的,例如窗口屏幕宽度window.screen.width(例如1024),当用户缩放时不会更改。

动机:当用户缩放时,我希望增加画布的宽度和高度(同时保持style.width和style.height相同的CSS像素值),对上下文进行scale()操作,并在更清晰的放大画布上重新绘制。

我已经阅读了Quirksmode的“两个视口的故事”Surfin' Safari上的高DPI网站,但它们都没有说如何获得比例。我目前唯一的想法是收集mousemove事件并测量event.clientX变化除以event.screenX的变化,或者通过编程方式创建使用moz--min-device-pixel-ratio的媒体查询,使用getComputedStyle()测试规则是否匹配,并通过二分搜索缩小范围。希望有更简单/可靠的方法。

编辑:我尝试在Chrome、Safari和Firefox 4中使用@media (-webkit-min-device-pixel-ratio:1)查询,显然Webkit将该属性视为常数设备像素与屏幕像素比(缩放时不会改变),而Firefox 4将其视为设备像素与CSS像素比(缩放时会增加)。因此,在Firefox 4中,我可以使用二进制搜索发现CSS像素/设备像素比,但在Webkit中则不行。


虽然依赖Flash,但您可能会发现这个链接很有用:http://stackoverflow.com/questions/5024493/browser-viewport-size-in-device-pixels/ - jedierikb
2
这是一个不错的问题,但已经过去几年了。其中一个答案提到了FF29,而我们现在已经到了53。如果时间允许,您可以选择最佳答案并提供有关此信息状态的更新吗? :-) - Nolo
4个回答

72

在基于Webkit的浏览器中,你可以使用JavaScript直接获取设备像素比,方法是使用window.devicePixelRatio。我已在Google Chrome、Android浏览器(2.2+)和移动版Safari上使用过。不过我不清楚其他浏览器的情况。


4
window.devicePixelRatio 可以在 Opera (Presto 2.8+) 上使用。了解更多请查看 http://www.opera.com/docs/specs/presto28/#changes。 - ryanve
7
即使 Kindle Fire HD 7" 的像素密度为 150%,但其 window.devicePixelRatio 的值仍为 1。 - Per Quested Aronsson
1
自Firefox 29版本以来,如果用户缩放了窗口,它仍然会错误地计算window.devicePixelRatio。 Firefox会以设备的像素比(例如:“Retina”类型显示器为2.0)呈现页面,但随后返回实际计算出的像素比(例如:在3倍窗口缩放下,devicePixelRatio将返回2.0 * 3 = 6.0)。这会对canvas元素造成混乱。 - bob
1
从Firefox 18开始,当浏览器缩放时,Mozilla会更改devicePixelRatio值,因此“device..”是具有误导性的。 - davidcondrey

25

您始终可以使用以下方法,并且它在所有浏览器中都能正常工作

window.getDevicePixelRatio = function () {
    var ratio = 1;
    // To account for zoom, change to use deviceXDPI instead of systemXDPI
    if (window.screen.systemXDPI !== undefined && window.screen.logicalXDPI       !== undefined && window.screen.systemXDPI > window.screen.logicalXDPI) {
        // Only allow for values > 1
        ratio = window.screen.systemXDPI / window.screen.logicalXDPI;
    }
    else if (window.devicePixelRatio !== undefined) {
        ratio = window.devicePixelRatio;
    }
    return ratio;
};

1
很棒,可以在FF、Chrome、IE、Edge上运行,即使是缩放因素也没有问题!还在iOS 10上进行了测试。 - spaark

3

有一种更好的CSS / JS解决方案:

/** sample media query for pixel-ratio=2" **/
@media  
(-webkit-min-device-pixel-ratio: 2), 
(min-resolution: 192dpi) { 
  .pixel-ratio-holder:before {
   content: "2";
  }
}


function jsPixelRatio(){
   return window.getComputedStyle(document.querySelector('.pixel-ratio-holder'), 'before').getPropertyValue('content').replace(/[^a-z]/g,'') * 1;
}

2
好的技巧。需要注意的是它似乎在document.ready()之前不起作用。 - commonpike

0

如何获取设备像素比

此示例使用window.devicePixelRatio作为起点并且还使用window.matchMedia() Web API作为备用计算。

这两个功能的浏览器支持非常好,因此对于大多数用例来说,这应该非常有效。

以下是一个检索此信息的函数,最初由PatrickJS编写并作为GitHub Gist发布

function getDevicePixelRatio() {
    var mediaQuery;
    var is_firefox = navigator.userAgent.toLowerCase().indexOf('firefox') > -1;

    if (window.devicePixelRatio !== undefined && !is_firefox) {
        return window.devicePixelRatio;
    } else if (window.matchMedia) {
        mediaQuery = "(-webkit-min-device-pixel-ratio: 1.5),\
          (min--moz-device-pixel-ratio: 1.5),\
          (-o-min-device-pixel-ratio: 3/2),\
          (min-resolution: 1.5dppx)";
        if (window.matchMedia(mediaQuery).matches) {
            return 1.5;
        }
        mediaQuery = "(-webkit-min-device-pixel-ratio: 2),\
          (min--moz-device-pixel-ratio: 2),\
          (-o-min-device-pixel-ratio: 2/1),\
          (min-resolution: 2dppx)";
        if (window.matchMedia(mediaQuery).matches) {
            return 2;
        }
        mediaQuery = "(-webkit-min-device-pixel-ratio: 0.75),\
          (min--moz-device-pixel-ratio: 0.75),\
          (-o-min-device-pixel-ratio: 3/4),\
          (min-resolution: 0.75dppx)";
        if (window.matchMedia(mediaQuery).matches) {
            return 0.7;
        }
    } else {
        return 1;
    }
}

CanIUse: window.devicePixelRatio, Window.matchMedia()

有用的链接: MDN - window.devicePixelRatio, MDN - Window.matchMedia()


1
将来,当您从其他来源适应代码或内容时,请确保适当地引用它。您在这里放置了链接,但是您将其埋藏在标题“来源”下面的底部,而不是直接与复制的代码一起包含。此外,您需要包括原始作者的姓名。我已经为您做出了更改;请记住这一点。谢谢! - Cody Gray

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接