【问题标题】:What are best practices for detecting pixel ratio/density?检测像素比率/密度的最佳做法是什么?
【发布时间】:2013-05-08 15:29:15
【问题描述】:

我目前在我的网站上使用 JavaScript 进行移动设备检测,这样我就可以为移动或桌面用户提供不同的内容。

目前我使用window.devicePixelRatioscreen.width 来判断用户是否在移动设备上,如下所示:

var isMobileScreenWidth = ((screen.width / window.devicePixelRatio) < 768)

768px 是我们定义移动或桌面的点,因此 767 及以下为移动,768 及以上为桌面。

这很好用,但我最近遇到了 Firefox 的一个问题,当 Firefox 放大和缩小时,它会更改 window.devicePixelRatio,所以:

zoom = 30%, window.devicePixelRatio = 0.3
zoom = 100%, window.devicePixelRatio = 1.0
zoom = 300%, window.devicePixelRatio = 3.0

这现在给我带来了一个问题,因为任何在 Firefox 上放大浏览器的用户都会获得该网站的移动版本。

我想知道是否有人知道获得与桌面浏览器不同的像素密度的不同或更好的方法。

我也使用了少量的用户代理检测,但是因为跟上不断变化的移动用户代理列表是一项艰巨的工作,所以我不可能同时依赖屏幕分辨率和用户代理同时。

如果有人对此有任何想法并且可以提供帮助,那就太棒了。

更新:

我刚刚遇到这个:

window.screen.availWidth / document.documentElement.clientWidth

这篇文章中建议了这个快速的数学:

window.devicePixelRatio does not work in IE 10 Mobile?

我已经对其进行了测试,它可以在 Firefox 中运行,并解决了我的问题,但不幸的是,现在在 Chrome 中出现了问题,所以:

Chrome zoom = 100%,
window.devicePixelRatio = 1.0,
window.screen.availWidth / document.documentElement.clientWidth = 3.0

我似乎找不到适用于所有情况的可靠解决方案。

【问题讨论】:

  • 您不应该使用设备像素比来检查移动设备:一些非移动设备是“视网膜”(iPad、mac book pro...)并且会显示移动设备样式。仅用于高清图像。
  • @Yukulélé 我明白你的担忧。这就是为什么我将screen.width 除以window.devicePixelRatio 然后检查其结果是否小于768px(iPad 的宽度)。这样做会阻止大多数平板设备看到移动风格。尽管像 Kindle Fire 这样的平板设备确实展示了移动风格,因为它们是较小的平板电脑。我不认为这是一个问题,因为这些设备的移动样式显示得很好。

标签: javascript mobile device-detection pixel-ratio


【解决方案1】:

您应该通过&lt;meta name="viewport" content="width=device-width"/&gt;@-ms-viewport {width:device-width} 功能利用制造商的提示。它基本上暴露了设备制造商在给定屏幕像素密度的情况下认为最佳的默认缩放。完成此操作后,当您致电 window.innerWidth 时,它将为您提供原始方程式的用途,但不依赖于像素密度的测量。

避免依赖window.devicePixelRatio 做任何事情。它的意义和它返回的价值目前处于不断变化的状态,你现在基于它所做的任何事情很可能很快就会崩溃。

注意: 元视口仅适用于 Android、iOS 和 Windows Phone 8。@-ms-viewport 仅(正确)适用于 IE10 Metro,并且可能会干扰 Windows Phone 8 上的正确元视口行为。

【讨论】:

  • 非常感谢您回复我这个问题我已经完全迷失了这个解决方案。因此,如果您不认为使用 window.devicePixelRatio 是一个安全的选择,您会使用什么来代替?我已经查看了许多用于检测移动设备的选项,不幸的是,服务器端解决方案对我来说是不可能的,所以 JavaScript 是我唯一的选择。
  • 一个想法是强制垂直滚动条出现在css中,然后比较document.documentElement.clientWidthwindow.innerWidth。它们在移动环境中应该相等(没有捏缩放),但在窗口桌面环境中则不同。
  • 我对此投了反对票,因为这不允许开发人员完全控制 HTML 应用程序的尺寸(似乎也不存在任何此类机制)。这不是你的错,而是网络技术的限制。与原生开发不同,无法始终如一地计算 1 点在现实世界中真正衡量的指标。
  • 我会使用 document.documentElement.clientWidth quirksmode.org/mobile/tableViewport.html 而不是 window.innertWidth ,此外,Windows Phone 8.1 浏览器不支持 devicePixelRatio。
【解决方案2】:

有一个获取设备像素比的通用解决方案

下一个代码使用window.devicePixelRatio 作为起点也有一个基于window.matchMedia() Web API 的后备。

浏览器对这两个功能的支持几乎是完美的,所以这应该适用于大多数用例。

这是一个检索此信息的函数,originally written by PatrickJS and published as a 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;
    }
}

有用的链接MDN - window.devicePixelRatioMDN - Window.matchMedia()

可以使用window.devicePixelRatioWindow.matchMedia()

【讨论】:

  • 2019年最好的办法是return window.devicePixelRatio || 1;
  • @Finesse 不能可靠地用于 Safari 12.x(无论缩放级别如何,都获得相同的值)。
  • @onassar,答案中的代码和 matchMedia 解决方案尤其在 Safari 12.1 中给出了相同的结果,因此它们并不更精确
  • 对不起?我是说在 Safari 12.x 中,当用户放大/缩小时运行该命令不会返回新值。每次 unfort 都返回相同的值。
猜你喜欢
  • 2020-09-07
  • 2010-09-09
  • 2018-04-08
  • 1970-01-01
  • 2012-11-30
  • 2012-06-08
  • 2011-09-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多