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

时间:2014-02-10 10:56:31

标签: android javascript google-chrome

问题

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

之前的研究

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

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

我想通过将内容限制在Android上的Chrome来探索简单解决方案的存在。

注意

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

13 个答案:

答案 0 :(得分:114)

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

这是一个非常漫长而复杂的故事,请原谅我。

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

  

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

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

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

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

通过使用宽度为“device-width”的视口,您可以免于将每个设备的视口宽度设置为最佳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的方式

资源:

答案 1 :(得分:11)

根据马特的回答,我做了一个测试:

// 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?

不。

因此,似乎无法在网络浏览器中获得真实的物理价值。

答案 2 :(得分:6)

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

<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>

答案 3 :(得分:5)

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

Device display properties

调用属性:

resolution_(width|height)

physical_display_(width|height)

长版:

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

User Agent string

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

WURFL

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

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

Download WURFL

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

答案 4 :(得分:2)

我用我的一个网络项目解决了这个问题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设置为当宽度小于284px时显示1列,而不管像素密度如何;然后在284px和568px之间的两列;然后是852px以上的3列。它看起来要简单得多,因为浏览器现在会自动进行像素密度计算。

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

答案 5 :(得分:1)

使用getPPI()函数(Mobile web: how to get physical pixel size?),获取1英寸内存使用此公式:

var ppi = getPPI();
var x   = ppi * devicePixelRatio * screen.pixelDepth / 24;
$('#Cubo').width (x);
$('#Cubo').height(x);

<div id="Cubo" style="background-color:red;"></div>

答案 6 :(得分:1)

作为对使用WURFL查找解决方案的zehelvion回复的回应,还值得一提的是WURFL也可以JavaScript snippet的形式提供。

wurfl.io提供的免费版中,您不会获得有关屏幕和分辨率的信息(仅限设备名称,外形尺寸和移动/非移动设备),但也有商业版本{ {3}}。

答案 7 :(得分:1)

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

您可以使用window.devicePixelRatio在JavaScript中获取屏幕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的实现不会太难。

答案 8 :(得分:1)

作为“对此问题没有好的解决方案”答案的补充,只需检查可以在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应该与屏幕尺寸无关,而为此已经有那么多单元)。

答案 9 :(得分:1)

我在您的评论中注意到,您实际上与观看者看到按钮等的大小有关。

我遇到了同样的问题,直到发现这仅仅是在HTML标头中添加一个meta标签来设置初始比例的问题:

<meta name="viewport" content="width=device-width, initial-scale=1">

答案 10 :(得分:0)

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
祝你好运 Danny117

答案 11 :(得分:0)

希望我能回答这个问题,但是构建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 :(得分:-1)

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

我已经在一些设备上整理了一个示例,以便查看结果。我的iPhone 6返回的值大约增加了33%。我的27&#34;我Mac上的桌面显示器报告为30&#34;监视。

&#13;
&#13;
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);
&#13;
&#13;
&#13;

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