在 Android 上的 Chrome 中获取物理屏幕尺寸/dpi/像素密度

IT技术 android javascript google-chrome
2021-01-26 02:12:36

问题

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

先前的研究

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

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

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

笔记

这完全是关于浏览器内的 javascript(或 css)解决方案,而不是本机应用程序的解决方案。

6个回答

您无法真正获得真实的物理尺寸或实际 DPI,即使可以,您也无法对它们做任何事情。

这是一个相当长而复杂的故事,所以请原谅我。

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

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

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

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

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

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

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

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

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

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

资源:

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

根据 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?

不。

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

我得到的结果和你一样,15.4" 但我的屏幕实际上是 21",太不同了
2021-03-17 02:12:36
@Michael He 将他的名字改为“matanster”并删除了他的答案(stackoverflow.com/a/24780546/454780)。
2021-03-18 02:12:36
我不确定你指的是什么答案(我在任何地方都没有看到“Matt”),但由于svgEl.screenPixelToMillimeterX显然没有被定义,我得到了 NaN
2021-04-06 02:12:36

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

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

您可以使用 WURFL 获取该信息:

设备显示属性

这些属性被称为:

resolution_(width|height)

physical_display_(width|height)

长版:

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

用户代理字符串

这是所有现代浏览器都可以提供的一条信息;它公开有关设备及其操作系统的信息。如果没有像WURFL.

WURFL

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

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

下载 WURFL

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

作为“这个问题没有好的解决方案”答案的补充,只需检查您可以在 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.

有了这个描述,似乎有一个解决方案。cm,mm并将in用于绘制与屏幕大小和分辨率无关的相同大小的内容。考虑到这一点,你可以期望的至少一个pxptpc可用于在像素级绘制,无论出于何种精密你想使用(否则,什么是在具有千万像素,右边的点?)。嗯,不。所有单位都是公制单位的分数,使所有这些单位只是不同的比例。故事中最糟糕的是,这些都不准确。只需使用 w3schools 示例(画一条 20 厘米的线并用尺子测量它)。

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

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