【问题标题】:Getting the physical screen dimensions / dpi / pixel density in Chrome on Android在 Android 上的 Chrome 中获取物理屏幕尺寸/dpi/像素密度
【发布时间】:2023-04-06 23:57:02
【问题描述】:

问题

是否有一种安全的方法可以在 Android 上的 Chrome 中获得实际正确的屏幕物理尺寸?如有必要,可以将旧版本的 Chrome 和 Android 排除在外。

先前的研究

stackoverflow 上有许多关于从 javascript(或 css)中获取设备的实际物理屏幕尺寸的死胡同问题。似乎 html api 标准化和实际浏览器实现之间没有融合,更不用说浏览器实现依赖于 OS api,而 OS api 又依赖于提供正确信息的硬件。

顺便说一句,一些先前的答案在假设当时盛行的某个像素密度方面是神秘的(2011 年等),因此毫无用处。其他与 webkit 有关,而 Chrome blink 可能已经取代了 chrome (?) 中的 webkit。

我想通过将事物限制为仅在 Android 上使用 Chrome 来探索一个简单解决方案的存在。

注意

这都是关于浏览器内部的 javascript(或 css)解决方案,而不是原生应用程序的解决方案。

【问题讨论】:

  • 那是完全错误的。我的用户界面想知道用户看到的按钮应该有多大。作为一名代码开发人员,你可能想太多了 ;)
  • 例如,按钮的大小不应该是视口的百分比,而是应该大到可以触摸。我不确定这对高质量设计有何意义。
  • @matt 是绝对正确的。 Web UX/UI 最重要的方面之一,尤其是在胖手指的世界中,是确保按钮既适合指针(在本例中为手指),也适合观看距离的大小从屏幕到眼睛。移动设备的这一新领域使问题变得复杂,因此物理屏幕尺寸检测更为重要。
  • 我 100% 支持你@matt。我不明白为什么 Mozilla 和 Google 不能只给我们一个 JavaScript 属性,例如 window.screenDensity,它包含你和我的设备每英寸的 物理 像素,马特,可以从那里获取它. window.screenHeightwindow.screenWidth 以物理毫米为单位也不错。
  • @Kinlan 物理屏幕尺寸通常很重要。这就是为什么原生开发目前比 Web 开发更强大的原因。例如,在原生环境中,我可以在所有现代设备上制作一个 1(现实世界)英寸宽的按钮。据我所知,这在网络环境中目前是不可能的。我错过了什么吗?

标签: android javascript google-chrome


【解决方案1】:

您无法真正获得真实的物理尺寸或实际 DPI,即使可以,您也无能为力。

这是一个相当长且复杂的故事,请见谅。

网络和所有浏览器都将 1px 定义为一个称为 CSS 像素的单位。 CSS 像素不是真正的像素,而是根据设备的视角被视为 1/96 英寸的单位。这被指定为reference pixel

参考像素是设备上一个像素的视角 像素密度为 96dpi,距离阅读者手臂的距离 长度。对于 28 英寸的标称臂长,视角为 因此大约为 0.0213 度。为了在手臂的长度上阅读,1px 因此 相当于大约 0.26 毫米(1/96 英寸)。

在 0.26 毫米的空间中,我们可能有很多真实的设备像素。

浏览器这样做主要是出于遗留原因 - 大多数显示器在网络诞生时是 96dpi - 但也是为了保持一致性,在“过去”中,在 800x600 的 15 英寸屏幕上的 22 像素按钮将是屏幕大小的两倍15 英寸显示器上的 22 像素按钮,分辨率为 1600x1200。在这种情况下,屏幕的 DPI 实际上是 2x(水平分辨率的两倍,但在相同的物理空间中)。这对 Web 和应用程序来说是一个糟糕的情况,因此大多数操作系统设计了许多方法来将像素值抽象为与设备无关的单位(Android 上的 DIPS、iOS 上的 PT 和 Web 上的 CSS Pixel) .

iPhone Safari 浏览器是第一个(据我所知)引入视口概念的浏览器。创建它是为了使完整的桌面样式应用程序能够在小屏幕上呈现。视口被定义为 960px 宽。这实际上将页面缩小了 3 倍(iphone 最初是 320 像素),因此 1 个 CSS 像素是物理像素的 1/3。当您定义一个视口时,虽然您可以让该设备匹配 1 个 CSS 像素 = 163dpi 的 1 个真实像素。

通过使用宽度为“设备宽度”的视口,您无需将每个设备的视口宽度设置为最佳 CSS 像素大小,浏览器只需为您完成这项工作。

随着双 DPI 设备的引入,手机制造商不希望移动页面看起来缩小 50%,因此他们引入了一个名为 devicePixelRatio 的概念(我相信是移动 webkit 上的第一个),这让他们可以保留 1 个 CSS 像素大约 1/96 英寸,但让您了解您的资产(例如图像)可能需要两倍大小。如果您查看 iPhone 系列,他们所有的设备都会在CSS pixels is 320px 中显示屏幕宽度,尽管我们知道这不是真的。

因此,如果您在 CSS 空间中将按钮设置为 22px,则物理屏幕上的表示为 22 * 设备像素比。其实我这么说,不完全是因为设备像素比也从来不准确,手机厂商把它设置为一个不错的数字,比如 2.0、3.0 而不是 2.1329857289918....

总之,CSS 像素与设备无关,让我们不必担心屏幕的物理尺寸和显示密度等。

这个故事的寓意是:不要担心了解屏幕的物理像素大小。你不需要它。 50px 在所有移动设备上看起来应该大致相同,它可能会略有不同,但 CSS Pixel 是我们构建一致文档和 UI 的设备独立方式

资源:

【讨论】:

  • 你说“你不能对他们做任何事”。我不同意。有了这些信息,我就可以设置 always 16 磅(实际英寸的 16/72 英寸)高度的字体。这是非常宝贵的,也是原生开发继续比 Web 开发更强大的原因之一。
  • 实际上,以像素为单位的实际屏幕尺寸的一个完全合理的用途是渲染具有适当分辨率的背景图像。
  • “50px 在所有移动设备上看起来应该大致相同”请证明使用例如 1200x1920 4 英寸手机和 1000x600 10 英寸平板电脑并排放置。
  • 我也不同意“你不能对它们做任何事情。”:你可以可靠地检测设备是手机还是平板电脑,并假设用户可以轻松地指向屏幕顶部他们的手指与否。
  • 非常详细的答案,但我不明白为什么说我们对屏幕的物理尺寸无能为力。我们可以利用这些信息做很多事情。例如,了解(或设置)屏幕上某物的物理尺寸。例如,显示将要打印的内容。增强现实的应用也很明显。如果答案能坚持问题,而不是决定人们想做什么,那就太好了。
【解决方案2】:

根据 Matanster 观察到 SVG 属性(例如 screenPixelToMillimeterX)的回答,我做了一个测试,看看它们是否有效:

(编辑:这些属性已从规范中删除(或从未删除),浏览器可能不再拥有(或从未拥有)它们,使我们远离了解实际的物理显示尺寸)。

// on Macbook Pro Retina (2880x1800, 15.4"), is the calculated diagonal size
// approximately 15.4? Let's see...

var svgEl = document.createElementNS("http://www.w3.org/2000/svg", "svg");
var screenWidthMillimeters = svgEl.screenPixelToMillimeterX * 2880;
var screenHeightMillimeters = svgEl.screenPixelToMillimeterY * 1800;
var screenDiagonalMillimeters = Math.sqrt(Math.pow(screenWidthMillimeters, 2) + Math.pow(screenHeightMillimeters, 2)); // pythagorean theorem
var screenDiagonalInches = (screenDiagonalMillimeters / 10 / 2.54); // (mm / 10mm/cm) / 2.54cm/in = in

console.log("The calculated diagonal of the screen is "+screenDiagonalInches+" inches. \nIs that close to the actual 15.4\"?");

这是输出:

The calculated diagonal of the screen is 35.37742738560738 inches. 
Is that close to the actual value of 15.4?

没有。

似乎还没有办法在网络浏览器中获得真实的物理值。

【讨论】:

  • 我不确定你指的是什么答案(我在任何地方都没有看到“Matt”),但由于svgEl.screenPixelToMillimeterX 显然没有被定义,我得到了 NaN。
  • 我得到的结果和你一样,15.4" 但我的屏幕实际上是21",差别太大了
  • @Michael 他改名为“matanster”并删除了他的回答(stackoverflow.com/a/24780546/454780)。
【解决方案3】:

您可以使用真实的物理单位创建任何页面元素并设置其宽度。例如

<div id="meter" style="width:10cm"></div>

然后得到它的宽度(以像素为单位)。例如下面的 html 代码(我使用 JQuery)以厘米为单位显示设备屏幕宽度

<script>
var pixPer10CM = $('#meter').width();
var CMPerPix = 10 / pixPer10CM;
var widthCM = screen.width * CMPerPix;

alert(widthCM);
</script>

【讨论】:

  • 哇,我从来没有意识到你可以用 css 做到这一点。这有多准确?您的浏览器如何知道屏幕的物理尺寸? caniuse.com 上的浏览​​器兼容性是否在某处?我找不到它。
  • W3C 网站说:“过去,CSS 要求实现即使在计算机屏幕上也能正确显示绝对单位。但由于不正确实现的数量超过了正确实现的数量,而且情况似乎没有改善, CSS 在 2011 年放弃了这一要求。目前,绝对单位必须仅在打印输出和高分辨率设备上才能正常工作。CSS 没有定义“高分辨率”的含义。但现在的低端打印机从 300dpi 和高分辨率开始- 结束屏幕为 200dpi,截止可能介于两者之间。”
  • 我认为浏览器和任何其他原生应用程序一样,可以通过 OS API 获得设备分辨率,由设备驱动程序提供给 OS。准确性取决于此信息。
  • 但设备分辨率与实际物理尺寸不一样。 14 英寸笔记本电脑和 15 英寸笔记本电脑可以具有相同的分辨率。
  • 不!你不能。 Css 中的 10 厘米在现实中会有不同的大小。如果它实际上有 10 厘米、12 厘米或 7 厘米,那纯属运气问题。这是我基于该解决方案返回错误值的 jsfiddle 演示,因为浏览器的行为总是像每英寸像素 (dpi):jsfiddle.net/Lzsm3zo9
【解决方案4】:

您可以通过 WURFL 获取该信息:

Device display properties

属性被调用:

resolution_(width|height)

physical_display_(width|height)

长版:

实现这一目标的最佳和最可靠的策略是将user agent string 从浏览器发送到数据库,例如WURFL(或其他)可以提供所需信息的最新数据库。

User Agent string

这是所有现代浏览器都可以提供的一条信息;它公开了有关设备及其操作系统的信息。如果没有像 WURFL 这样的字典的帮助,这对您的应用程序来说意义不大。

WURFL

这是一个常用于检测设备属性的数据库。

有了它,你或许可以准确支持市面上大部分的流行设备。 我会发布一个代码演示,但可以在WURFL 站点上下载。您可以在与库一起下载的示例/演示文件夹中找到这样的演示。

Download WURFL

以下是有关检查物理尺寸和分辨率的更多信息和说明: http://www.scientiamobile.com/forum/viewtopic.php?f=16&t=286

【讨论】:

    【解决方案5】:

    作为“这个问题没有好的解决方案”答案的补充,只需检查您可以在 CSS 上使用的单位 https://www.w3schools.com/cssref/css_units.asp

    Unit    Description
    cm      centimeters
    mm      millimeters
    in      inches (1in = 96px = 2.54cm)
    px *    pixels (1px = 1/96th of 1in)
    pt      points (1pt = 1/72 of 1in)
    pc      picas (1pc = 12 pt)
    
    * Pixels (px) are relative to the viewing device.
    For low-dpi devices, 1px is one device pixel (dot) of the display.
    For printers and high resolution screens 1px implies multiple device pixels.
    

    有了这个描述,似乎就有了解决办法。 cmmmin 将用于绘制具有相同尺寸的东西,而与屏幕尺寸和分辨率无关。考虑到这一点,您可以期望pxptpc 中的至少一个可用于在像素级别绘制,无论您想使用什么精度(否则,有什么意义百万像素,对吧?)。嗯,不。所有单位都是公制单位的分数,使所有这些单位只是不同的比例。故事中最糟糕的是,这些都不准确。只需使用 w3schools 示例(画一条 20 厘米的线并用尺子测量)。

    所以最后: - 没有办法准确地绘制具有物理尺寸的东西(cmmmin 和最终ptpc 应该是这种情况)。 - 没有办法独立于屏幕尺寸和分辨率绘制相同尺寸的东西(至少px应该是这种情况)。

    这既是实现问题(未使用实际屏幕尺寸)也是设计问题(为什么px 应该独立于屏幕尺寸,而已经有这么多单位)。

    【讨论】:

      【解决方案6】:

      我用我的一个网络项目http://www.vinodiscover.com 解决了这个问题,答案是你不能确定物理尺寸是多少,但你可以得到一个近似值。使用 JS 和/或 CSS,您可以找到视口/屏幕的宽度和高度,以及使用媒体查询的像素密度。例如:iPhone 5 (326 ppi) = 320px x 568px 和 2.0 像素密度,而三星 Galaxy S4 (441ppi) = 360px x 640px 和 3.0 像素密度。实际上,1.0 像素密度约为 150 ppi。

      鉴于此,我将 CSS 设置为在宽度小于 284 像素时显示 1 列,而不管像素密度如何;然后是 284px 和 568px 之间的两列;然后是 852px 以上的 3 列。它看起来要简单得多,因为现在浏览器会自动进行像素密度计算。

      http://www.quirksmode.org/blog/archives/2010/04/a_pixel_is_not.html

      【讨论】:

      【解决方案7】:

      作为对 zehelvion 关于使用 WURFL 查找分辨率的回复的回应,还值得一提的是,WURFL 也可以通过 JavaScript snippet 获得。

      wurfl.io 提供的免费版中,虽然您不会获得有关屏幕和分辨率的信息(只有设备名称、外形尺寸和移动/非移动),但也有带有more capabilities available here 的商业版本.

      【讨论】:

      • 我建议将其放在特定答案的 cmets 中。
      • 这是一个非常复杂的解决方案,它应该由浏览器本机提供。
      【解决方案8】:

      CSS 像素并不是我们真正的“设备独立像素”。 Web 平台由多种设备类型组成。虽然 CSS 像素在手持设备上看起来相当一致,但在典型的 96dpi 桌面显示器上会大 50%。见我的question。在某些情况下,这确实不是一件坏事,例如在更大的屏幕上字体应该更大,因为到眼睛的距离更大。但是 ui 元素尺寸应该非常一致。假设您的应用程序有一个顶栏,您希望它在桌面和移动设备上的厚度相同,默认情况下它会小 50%,这不好,因为可触摸元素应该更大。我发现的唯一解决方法是根据设备 DPI 应用不同的样式。

      您可以在 JavaScript 中使用 window.devicePixelRatio 获取屏幕 DPI。或 CSS 查询:

      @media  only screen and (-webkit-min-device-pixel-ratio: 1.3),
          only screen and (-o-min-device-pixel-ratio: 13/10),
          only screen and (min-resolution: 120dpi)
          {
           /* specific styles for handhelds/ high dpi monitors*/
          }
      

      我不知道如何在高 dpi 桌面显示器上应用它。也许元素太小了。网络平台没有提供更好的东西真是太可惜了。我想dip的实现不会太难。

      【讨论】:

      • 不,你不能。媒体查询正在做这种愚蠢的“假设 96dpi”废话,即他们对你撒谎关于读取的 DPI 是什么。
      【解决方案9】:

      我在您的 cmets 中注意到您实际上关心按钮等出现在查看器中的大小。

      我遇到了同样的问题,直到我发现只需在 HTML 标头中添加一个元标记来设置初始比例:

      &lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt;

      【讨论】:

        【解决方案10】:

        JqueryMobile width of element

        $(window).width();   // returns width of browser viewport
        $(document).width(); // returns width of HTML document
        

        JqueryMobile Height of element

        $(window).height();   // returns height of browser viewport
        $(document).height(); // returns height of HTML document
        

        祝你好运 丹尼117

        【讨论】:

        • 这些是虚拟维度,并不总是物理现实世界的维度。
        • 谢谢 我不知道
        【解决方案11】:

        希望我能回答这个问题,但是构建 API 的极客并没有提供基本的必需品,而且有时抽象的东西有点太多了。

        顺便说一句,我拥有 40 年的 UI 和软件设计设计经验,并且自“VESA”驱动程序出现之前就一直在努力实现这一点:)。

        对于触摸屏,我有一个叫做“fingerSize()”的东西,它是 1cm 的像素数(非常接近手指平均触摸区域的直径),但根基准是“dpcm”。

        你想要的另一件事是“视角” 用于查看和触摸功能的显示设备类型几乎决定了查看距离。

            (Not code but I wanted fixed width font)
        
            Hand held - Phone/Tablet         25cm 
            Touch screen / Desktop Monitor   40cm         ( seated or standing at a counter
                                                            with partially extended arm )
            "Personal" Touch kiosk        50cm -> 80cm ( a bit further away standing 
                                                         extended arms and standing back 
                                                         to view )
            Presentation Screen.          any distance ( angle of view derived from pixel
                                                         width of device. An ideal conventional cinema 
                                                         seat (as opposed to imax or immersive) 
                                                         you want about 50 degrees
                                                         between edges of the screen. from viewer POV )
        
            So what you want universally available is:
        
            device usage type.
            finger size in pixels (dots per CM)
            pixel dimensions of display.
        
            Then internally, when laying out and drawing you want the size/shape of a pixel 
            for the current transform. 
        

        这是我们试图在我们的 API 中提供的,但可惜在很多情况下很难获得。

        【讨论】:

          【解决方案12】:

          使用 getPPI() 函数 (Mobile web: how to get physical pixel size?),要获得一英寸的 id,请使用以下公式:

          var ppi = getPPI();
          var x   = ppi * devicePixelRatio * screen.pixelDepth / 24;
          $('#Cubo').width (x);
          $('#Cubo').height(x);
          
          <div id="Cubo" style="background-color:red;"></div>
          

          【讨论】:

          • 为什么是像素深度?!不是pixelDepth与颜色深度有关,在这种情况下我想知道它与这里的计算有什么关系......
          【解决方案13】:

          您可以粗略估计尺寸,但并不准确。

          我整理了一个示例,我已经在几个设备上进行了测试,看看结果如何。我的 iPhone 6 返回值大约大 33%。我的 Mac 上的 27 英寸桌面显示器报告为 30 英寸显示器。

          var $el = document.createElement('div');
          $el.style.width = '1cm';
          $el.style.height = '1cm';
          $el.style.backgroundColor = '#ff0000';
          $el.style.position = 'fixed';
          $el.style.bottom = 0;
          document.body.appendChild($el);
          var screenDiagonal = Math.sqrt(Math.pow((window.screen.width / $el.offsetWidth), 2) + Math.pow((window.screen.height / $el.offsetHeight), 2));
          var screenDiagonalInches = (screenDiagonal / 2.54);
          var str = [
            '1cm (W): ' + $el.offsetWidth + 'px',
            '1cm (H): ' + $el.offsetHeight + 'px',
            'Screen width: ' + window.screen.width + 'px',
            'Screen height: ' + window.screen.height + 'px',
            'Browser width: ' + window.innerWidth + 'px',
            'Browser height: ' + window.innerHeight + 'px',
            'Screen available width: ' + window.screen.availWidth + 'px',
            'Screen available height: ' + window.screen.availHeight + 'px',
            'Screen width: ' + (window.screen.width / $el.offsetWidth).toFixed(2) + 'cm',
            'Screen height: ' + (window.screen.height / $el.offsetHeight).toFixed(2) + 'cm',
            'Screen diagonal: ' + screenDiagonal.toFixed(2) + 'cm',
            'Screen diagonal: ' + screenDiagonalInches.toFixed(2) + 'in',
            'Device Pixel Ratio: ' + (window.devicePixelRatio || 1)
          ].join('\n');
          var $pre = document.createElement('pre');
          $pre.innerHTML = str;
          document.body.appendChild($pre);

          http://codepen.io/kus/full/xOAPYB/

          【讨论】:

          • 我的 40 英寸报告为 22 英寸。
          • 对我来说也不准确。我认为问题是由于window.devicePixelRatio。在 Apple Thunderbolt 屏幕上是 1,在 Macbook Pro Touchbar 15" 上是 2。这个值是否总是整数?这没有意义,因为它是一个比率。其他元素:stackoverflow.com/questions/16385573/…
          • 它在 2016 年可能不太好,但它报告我的台式 PC 的屏幕尺寸为 45"(实际尺寸为 40")和我的 Galaxy S10+ 的 10",两者都是足够接近,即区分不同缩放版本的 UI 和文档。不知道为什么要在所有变量前加上 $。
          猜你喜欢
          • 2017-04-22
          • 2020-04-29
          • 1970-01-01
          • 2023-04-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-03-04
          • 1970-01-01
          相关资源
          最近更新 更多