Obtener las dimensiones físicas de la pantalla / dpi / densidad de píxeles en Chrome en Android

88

Pregunta

¿Existe una manera segura de obtener las dimensiones físicas de pantalla realmente correctas en Chrome, en Android? Si es necesario, las versiones antiguas de Chrome y Android pueden quedar fuera de alcance.

Investigaciones anteriores

Hay numerosas preguntas sin salida en stackoverflow sobre cómo obtener las dimensiones reales de la pantalla física de un dispositivo desde javascript (o css). Parece que no hay convergencia entre la estandarización de la api html y las implementaciones reales del navegador en eso, sin mencionar que la implementación del navegador se basa en las api del sistema operativo, que a su vez dependen del hardware que proporciona la información correcta.

Algunas respuestas previas, por cierto, son arcanas (año 2011 y similares) al asumir una cierta densidad de píxeles que prevalecía en ese momento, y por lo tanto inútil. Otros se relacionan con webkit, mientras que Chrome blink puede haber reemplazado a webkit en Chrome (?).

Me gustaría explorar la existencia de una solución simple al restringir las cosas solo a Chrome en Android.

Nota

Se trata de una solución javascript (o css) dentro del navegador, no una solución para una aplicación nativa.

matanster
fuente
21
Eso es simplemente incorrecto. Mi interfaz de usuario quiere saber cosas como qué tan grande debe ser un botón como lo ve el usuario. es posible que esté pensando demasiado como desarrollador de código en eso;)
matanster
12
El tamaño de un botón, por ejemplo, no debe ser un porcentaje de la ventana gráfica, sino lo suficientemente grande como para tocarlo. No estoy seguro de cómo eso tiene sentido para un diseño de alta calidad.
matanster
16
@matt es absolutamente correcto. Uno de los aspectos más importantes de Web UX / UI, especialmente en un mundo de dedos gordos, es asegurarse de que los botones sean apropiados para el puntero, en este caso, un dedo, y que tengan el tamaño adecuado para la distancia de visualización. de la pantalla al ojo. Este nuevo ámbito de los dispositivos móviles ha complicado el asunto, por lo que la detección del tamaño de la pantalla física es aún más primordial.
Jason T Featheringham
7
Estoy 100% contigo @matt. No entiendo por qué Mozilla y Google no pueden simplemente darnos una propiedad de JavaScript como la window.screenDensityque contiene los píxeles físicos por pulgada del dispositivo que tú y yo, Matt, podemos tomar desde allí. window.screenHeighty window.screenWidthen milímetros físicos también estaría bien.
trusktr
7
@Kinlan El tamaño de la pantalla física es importante en general. Es por eso que el desarrollo nativo es más poderoso que el desarrollo web en este momento. En un entorno nativo, puedo hacer un botón de 1 pulgada (del mundo real) de ancho, en todos los dispositivos modernos, por ejemplo. Por lo que yo sé, esto no es posible actualmente en un entorno web. ¿Me he perdido algo?
trusktr

Respuestas:

118

Realmente no puede obtener las dimensiones físicas reales o el DPI real e incluso si pudiera, no puede hacer nada con ellos.

Esta es una historia bastante larga y compleja, así que perdóname.

La web y todos los navegadores definen 1px como una unidad llamada píxel CSS. Un píxel CSS no es un píxel real, sino una unidad que se considera 1/96 de pulgada según el ángulo de visión del dispositivo. Esto se especifica como un píxel de referencia .

El píxel de referencia es el ángulo visual de un píxel en un dispositivo con una densidad de píxeles de 96 ppp y una distancia del lector de la longitud de un brazo. Para una longitud nominal del brazo de 28 pulgadas, el ángulo visual es por lo tanto de aproximadamente 0.0213 grados. Para la lectura con el brazo extendido, 1 px corresponde a aproximadamente 0,26 mm (1/96 pulgada).

En 0,26 mm de espacio, podríamos tener muchos píxeles de dispositivo reales.

El navegador hace esto principalmente por razones heredadas (la mayoría de los monitores tenían 96 ppp cuando nació la web), pero también por coherencia, en los "viejos tiempos", un botón de 22 píxeles en una pantalla de 15 pulgadas a 800 x 600 sería el doble del tamaño de un botón de 22 píxeles en un monitor de 15 pulgadas a 1600x1200. En este caso, el DPI de la pantalla es en realidad 2x (el doble de la resolución horizontalmente pero en el mismo espacio físico). Esta es una mala situación para la web y las aplicaciones, por lo que la mayoría de los sistemas operativos idearon muchas formas de abstraer los valores de píxeles en unidades independientes del dispositivo (DIPS en Android, PT en iOS y CSS Pixel en la web ).

El navegador Safari de iPhone fue el primero (que yo sepa) en introducir el concepto de ventana gráfica. Esto fue creado para permitir que las aplicaciones de estilo de escritorio completo se rendericen en una pantalla pequeña. La ventana gráfica se definió con 960 píxeles de ancho. Básicamente, esto hizo que la página se alejara 3 veces (el iPhone originalmente tenía 320 px), por lo que 1 píxel CSS es 1/3 de un píxel físico. Cuando definió una ventana gráfica, sin embargo, podría hacer que este dispositivo coincidiera con 1 píxel CSS = 1 píxel real a 163 ppp.

Al utilizar una ventana gráfica en la que el ancho es "ancho del dispositivo" te libera de tener que establecer la anchura de la ventana gráfica por dispositivo al tamaño de píxel CSS óptimo, el navegador simplemente lo hace por ti.

Con la introducción de dispositivos de doble DPI, los fabricantes de teléfonos móviles no querían que las páginas móviles parecieran un 50% más pequeñas, por lo que introdujeron un concepto llamado devicePixelRatio (creo que primero en un webkit móvil), esto les permite mantener 1 píxel CSS en aproximadamente 1 /. 96 de pulgada, pero le permite comprender que es posible que sus recursos, como las imágenes, tengan el doble de tamaño. Si observa la serie iPhone, todos sus dispositivos dicen que el ancho de la pantalla en píxeles CSS es 320px , aunque sabemos que esto no es cierto.

Por lo tanto, si hizo que un botón tenga 22 píxeles en el espacio CSS, la representación en la pantalla física es una proporción de píxeles del dispositivo de 22 *. En realidad, digo esto, no es exactamente esto porque la relación de píxeles del dispositivo tampoco es exacta, los fabricantes de teléfonos lo configuran en un buen número como 2.0, 3.0 en lugar de 2.1329857289918 ...

En resumen, los píxeles CSS son independientes del dispositivo y no nos permiten preocuparnos por los tamaños físicos de las pantallas y las densidades de visualización, etc.

La moraleja de la historia es: no se preocupe por comprender el tamaño de píxel físico de la pantalla. No lo necesitas. 50px debe verse aproximadamente igual en todos los dispositivos móviles, puede variar un poco, pero el píxel CSS es la forma independiente de nuestro dispositivo de crear documentos e interfaces de usuario consistentes

Recursos:

Kinlan
fuente
1
@matt será lo mismo en las tabletas. Como sucede con los libros retina mac. El objetivo es que el "Píxel CSS" sea relativamente uniforme en todas las plataformas, especialmente si establece el ancho de la ventana gráfica = ancho del dispositivo.
Kinlan
14
Dijiste "no puedes hacer nada con ellos". Estoy en desacuerdo. Con esa información, podría establecer una fuente que siempre tenga 16 puntos (16/72 de una pulgada del mundo real) de altura. Eso es invaluable y una de las razones por las que el desarrollo nativo sigue siendo más poderoso que el desarrollo web.
trusktr
8
En realidad, un uso perfectamente razonable del tamaño de pantalla real en píxeles es renderizar una imagen de fondo con la resolución adecuada.
WhyNotHugo
2
"50px debe verse aproximadamente igual en todos los dispositivos móviles", demuéstrelo usando, por ejemplo, un teléfono de 1200 x 1920 de 4 pulgadas y una tableta de 1000 x 600 de 10 pulgadas uno al lado del otro.
iloveregex
6
También estoy en desacuerdo con "no puedes hacer nada con ellos": puedes detectar si el dispositivo es un teléfono o una tableta de manera confiable y asumir que el usuario puede señalar fácilmente la parte superior de la pantalla con el dedo o no.
Brian Cannard
11

Basado en la respuesta de Matt, hice una prueba:

// 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\"?");

Esta es la salida:

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

¡No!

Por lo tanto, parece que todavía no hay forma de obtener valores físicos reales en un navegador web.

trusktr
fuente
No estoy seguro de a qué respuesta te refieres (no veo un "Matt" en ninguna parte), pero obtengo NaN debido a que svgEl.screenPixelToMillimeterXaparentemente no está definido.
Michael
6

Puede crear cualquier elemento de página y establecer su ancho utilizando unidades físicas reales. Por ejemplo

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

Y luego obtenga su ancho en píxeles. Por ejemplo, el código html a continuación (usé JQuery) muestra el ancho de la pantalla del dispositivo en centímetros

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

alert(widthCM);
</script>
Miguel
fuente
Vaya, nunca me di cuenta de que podrías hacer esto con CSS. ¿Qué tan exacto es esto? ¿Cómo sabe su navegador las dimensiones físicas de su pantalla? ¿Es la compatibilidad del navegador para esto en caniuse.com en alguna parte? No lo encuentro.
Jake Wilson
4
El sitio del W3C dice: "En el pasado, CSS requería que las implementaciones mostraran unidades absolutas correctamente incluso en las pantallas de las computadoras. Pero como el número de implementaciones incorrectas superó a las correctas y la situación no pareció mejorar, CSS abandonó ese requisito en 2011. Actualmente , las unidades absolutas deben funcionar correctamente solo en la salida impresa y en dispositivos de alta resolución. CSS no define lo que significa "alta resolución". Pero como las impresoras de gama baja hoy en día comienzan a 300 ppp y las pantallas de gama alta a 200 ppp, el límite probablemente esté en algún punto intermedio ".
Mike
1
Creo que el navegador, como cualquier otra aplicación nativa, puede obtener la resolución del dispositivo a través de la API del sistema operativo, proporcionada al sistema operativo por el controlador del dispositivo. La precisión depende de esta información.
Mike
Pero la resolución del dispositivo no es lo mismo que las dimensiones físicas reales. Una computadora portátil de 14 "y una computadora portátil de 15" podrían tener la misma resolución.
Jake Wilson
6
¡No! No puedes. 10cm en CSS tendrán un tamaño diferente en realidad. Es pura suerte si realmente tendrá 10 cm, 12 cm o 7 cm. Aquí está mi demostración de jsfiddle basada en esa solución que devuelve valores incorrectos, ya que los navegadores siempre se comportan como si tuvieran píxeles por pulgada (dpi): jsfiddle.net/Lzsm3zo9
Dariusz Sikorski
5

Puede obtener esa información con WURFL:

Propiedades de visualización del dispositivo

Los atributos se denominan:

resolution_(width|height)

physical_display_(width|height)

Versión larga:

La mejor y más confiable estrategia para lograr esto es enviar user agent stringdesde el navegador a una base de datos como WURFL(u otra) base de datos actualizada que pueda proporcionar la información necesaria.

Cadena de agente de usuario

Esta es una información que pueden proporcionar todos los navegadores modernos; expone información sobre el dispositivo y su sistema operativo. Simplemente no es lo suficientemente significativo para su aplicación sin la ayuda de un diccionario como WURFL.

WURFL

Esta es una base de datos que se usa comúnmente para detectar propiedades de dispositivos.

Con él, es posible que pueda admitir con precisión la mayoría de los dispositivos populares del mercado. Publicaría una demostración de código, pero hay una disponible con la descarga en el WURFLsitio. Puede encontrar una demostración de este tipo en la carpeta examples / demo que se descarga con la biblioteca.

Descarga WURFL

Aquí hay más información y una explicación sobre cómo verificar el tamaño físico y la resolución: http://www.scientiamobile.com/forum/viewtopic.php?f=16&t=286

AturSams
fuente
3

Como complemento a la respuesta "no hay una buena solución para este problema", solo verifique las unidades que puede usar en 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.

Con esta descripción parece que hay una solución. cm, mmy inse usaría para dibujar algo con el mismo tamaño independientemente del tamaño y la resolución de la pantalla. Con esto en mente, puede esperar que al menos uno de px, ptopc se pueda usar para dibujar a nivel de píxel, para cualquier precisión que le gustaría usar (de lo contrario, ¿qué sentido tiene tener millones de píxeles, verdad?). Bueno no. Todas las unidades son fracciones de una unidad métrica, por lo que todas estas unidades son escalas diferentes. Y lo peor de la historia es el hecho de que ninguno de estos es exacto. Simplemente juegue con el ejemplo de w3schools (dibuje una línea de 20 cm y mida con una regla).

Así que al final: - no hay manera de dibujar algo con precisión las dimensiones físicas (que debería ser el caso cm, mm, in, y, finalmente, pte pc). - No hay forma de dibujar algo con el mismo tamaño independientemente del tamaño de la pantalla y la resolución (que debería ser el caso con al menos px).

Esto es tanto un problema de implementación (no se utiliza el tamaño real de la pantalla) como un problema de diseño (por qué debería pxser independiente del tamaño de la pantalla cuando ya hay tantas unidades para eso).

Tom
fuente
2

Abordé este problema con uno de mis proyectos web http://www.vinodiscover.com La respuesta es que no se puede saber con certeza cuál es el tamaño físico, pero se puede obtener una aproximación. Usando JS y / o CSS, puede encontrar el ancho y alto de la ventana / pantalla, y la densidad de píxeles usando consultas de medios. Por ejemplo: iPhone 5 (326 ppi) = 320px por 568px y una densidad de 2.0 píxeles, mientras que un Samsung Galaxy S4 (441ppi) = 360px x 640px y una densidad de 3.0 píxeles. Efectivamente, una densidad de 1.0 píxeles es alrededor de 150 ppp.

Dado esto, configuro mi CSS para mostrar 1 columna cuando el ancho es menor a 284px, independientemente de la densidad de píxeles; luego dos columnas entre 284px y 568px; luego 3 columnas por encima de 852px. Es mucho más simple de lo que parece, ya que los navegadores ahora hacen los cálculos de densidad de píxeles automáticamente.

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

Apollo Clark
fuente
3
En el desarrollo nativo puede obtener el valor exacto. +1 para nativo, -1 para web.
trusktr
¿Puede obtener el tamaño físico exacto en Android?
Apollo Clark
2

Como respuesta a la respuesta de zehelvion sobre el uso de WURFL para encontrar la resolución, también vale la pena mencionar que WURFL también está disponible como un fragmento de JavaScript .

Sin embargo , en la edición gratuita que se ofrece en wurfl.io , no obtendrá información sobre la pantalla y la resolución (solo el nombre del dispositivo, el factor de forma y móvil / no móvil), pero también hay una versión comercial con más capacidades disponibles aquí .

jonarnes
fuente
3
Sugiero que esto esté en los comentarios a esa respuesta en particular.
mirada oscura
1
esta es una solución ridículamente complicada para algo que el navegador debería proporcionar de forma nativa.
Michael
2

Los píxeles CSS no son realmente nuestro "píxel independiente del dispositivo". La plataforma web consta de una variedad de tipos de dispositivos. Si bien los píxeles de CSS parecen tener un aspecto bastante uniforme en las computadoras de mano, serán un 50% más grandes en un monitor de escritorio típico de 96 ppp. Vea mi pregunta . Esto no es nada malo en algunos casos, por ejemplo, las fuentes deberían ser más grandes en una pantalla más grande, ya que la distancia al ojo es mayor. Pero las dimensiones de los elementos de la interfaz de usuario deberían ser bastante consistentes. Digamos que su aplicación tiene una barra superior, preferiría que tuviera el mismo grosor en computadoras de escritorio y móviles, por defecto será un 50% más pequeña, lo cual no es bueno, porque los elementos táctiles deberían ser más grandes. La única solución que he encontrado es aplicar diferentes estilos según el DPI del dispositivo.

Puede obtener DPI de pantalla en JavaScript con window.devicePixelRatio. O consulta 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*/
    }

Sin embargo, no sé cómo funcionaría la aplicación de esto en un monitor de escritorio de alta resolución. Quizás los elementos serían demasiado pequeños. Realmente es una pena que la plataforma web no ofrezca nada mejor. Supongo que la implementación de dip no sería demasiado difícil.

Maciej Krawczyk
fuente
no, no puedes. Las consultas de medios están haciendo esta estúpida porquería de "asumir 96 ppp", es decir, te están mintiendo sobre lo que es el DPI leído.
Michael
1

Noté en sus comentarios que en realidad le preocupaba el tamaño que aparecen los botones y demás para el espectador.

Estaba teniendo el mismo problema, hasta que descubrí que solo era cuestión de agregar una metaetiqueta al encabezado HTML para establecer la escala inicial:

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

Dan Kennedy
fuente
0

JqueryMobile ancho del elemento

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

JqueryMobile Altura del elemento

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

Buena Suerte Danny117

danny117
fuente
3
Esas son dimensiones virtuales, que no siempre son dimensiones físicas del mundo real.
trusktr
Gracias No sabía eso
danny117
0

Usando la función getPPI () ( Web móvil: ¿cómo obtener el tamaño de píxel físico? ), Para obtener una identificación de una pulgada, use esta fórmula:

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

<div id="Cubo" style="background-color:red;"></div>
Pilo
fuente
5
¿Por qué pixelDepth? pixelDepth no está relacionado con la profundidad de color, en cuyo caso me pregunto cómo es relevante para el cálculo aquí ...
matanster
0

Ojalá pudiera responder a esto, pero los geeks que crean API no proporcionan las necesidades básicas y las cosas abstractas a veces.

Por cierto, tengo 40 años de experiencia en diseño de UI y diseño de software y he estado presionando para tener esto por lo que parece una eternidad desde antes de los días de los controladores "VESA" :).

Para la pantalla táctil, tenía una cosa que llamé "fingerSize ()", que era el número de píxeles de 1 cm (muy cerca del diámetro del área táctil promedio del dedo), pero el datmum de la raíz es "dpcm".

La otra cosa que desea para una pantalla es "ángulo de visión". El tipo de dispositivo de visualización para visualización y función táctil define prácticamente la distancia de visualización.

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

Esto es lo que intentamos proporcionar en nuestras API, pero lamentablemente es difícil de conseguir en muchos casos.

Peterk
fuente
-1

Puede obtener una estimación aproximada del tamaño, pero no es precisa.

He reunido un ejemplo que he probado en un par de dispositivos para ver cuáles fueron los resultados. Mi iPhone 6 devuelve valores un 33% más grandes. Mi monitor de escritorio de 27 "en mi Mac informó como un monitor de 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/

Kus
fuente
1
Mi 40 pulgadas informó como 22 pulgadas.
RobotRock
No es exacto para mí tampoco. Creo que el problema se debe a window.devicePixelRatio. Es 1 en una pantalla Apple Thunderbolt y 2 en una Macbook Pro Touchbar de 15 ". ¿Este valor es siempre un número entero? Esto no tendría sentido ya que es una proporción. Otros elementos: stackoverflow.com/questions/16385573/…
Tom