Obtenir les dimensions physiques de l'écran / dpi / densité de pixels dans Chrome sur Android

88

Question

Existe-t-il un moyen sûr d'obtenir les dimensions physiques de l'écran réellement correctes dans Chrome, sur Android? Si nécessaire, les anciennes versions de Chrome et d'Android peuvent être laissées hors de portée.

Recherches antérieures

Il existe de nombreuses questions sans issue sur le stackoverflow sur l'obtention des dimensions physiques réelles de l'écran d'un périphérique à partir de javascript (ou css). Il semble qu'il n'y ait pas de convergence entre la normalisation des api html et les implémentations réelles du navigateur dans la mesure où, sans parler de l'implémentation du navigateur, elle repose sur les api du système d'exploitation qui, à leur tour, reposent sur le matériel fournissant les bonnes informations.

Certaines réponses antérieures sont d'ailleurs obscures (année 2011 et autres) en supposant une certaine densité de pixels qui prévalait à ce moment-là, et donc inutile. D'autres se rapportent à Webkit alors que Chrome Blink peut avoir remplacé Webkit dans Chrome (?).

Je voudrais explorer l'existence d'une solution simple en limitant les choses uniquement à Chrome sur Android.

Remarque

Il s'agit d'une solution javascript (ou css) dans le navigateur, pas d'une solution pour une application native.

matanster
la source
21
C'est tout simplement faux. Mon interface utilisateur veut savoir des choses comme la taille d'un bouton tel que l'utilisateur le voit. vous pensez peut-être trop en tant que développeur de code;)
matanster
12
La taille d'un bouton, par exemple, ne doit pas être un pourcentage de la fenêtre, mais assez grande pour être touchée. Je ne sais pas en quoi cela a du sens pour un design de haute qualité.
matanster le
16
@matt est absolument correct. L'un des aspects les plus importants de Web UX / UI, en particulier dans un monde à gros doigts, est de s'assurer que les boutons sont à la fois appropriés pour le pointeur - dans ce cas, un doigt - et correctement dimensionnés pour la distance de visualisation. d'un écran à l'autre. Ce nouveau domaine des appareils mobiles a compliqué le problème, de sorte que la détection de la taille physique de l'écran est encore plus primordiale.
Jason T Featheringham
7
Je suis à 100% avec vous @matt. Je ne comprends pas pourquoi Mozilla et Google ne peuvent pas simplement nous donner une propriété JavaScript comme window.screenDensitycelle qui contient les pixels physiques par pouce de l'appareil que vous et moi, Matt, pouvons prendre à partir de là. window.screenHeightet window.screenWidthen millimètres physiques serait bien aussi.
trusktr
7
@Kinlan La taille physique de l'écran est importante en général. C'est pourquoi le développement natif est actuellement plus puissant que le développement Web. Dans un environnement natif, je peux créer un bouton de 1 pouce (dans le monde réel), sur tous les appareils modernes, par exemple. Ce n'est actuellement pas possible dans un environnement Web, pour autant que je sache. Ai-je manqué quelque chose?
trusktr

Réponses:

118

Vous ne pouvez pas vraiment obtenir les dimensions physiques réelles ou le DPI réel et même si vous le pouviez, vous ne pouvez rien faire avec eux.

C'est une histoire assez longue et complexe, alors pardonnez-moi.

Le Web et tous les navigateurs définissent 1px comme une unité appelée pixel CSS. Un pixel CSS n'est pas un vrai pixel, mais plutôt une unité considérée comme 1 / 96e de pouce en fonction de l'angle de vue de l'appareil. Ceci est spécifié comme pixel de référence .

Le pixel de référence est l'angle visuel d'un pixel sur un appareil avec une densité de pixels de 96 dpi et une distance du lecteur d'une longueur de bras. Pour une longueur de bras nominale de 28 pouces, l'angle visuel est donc d'environ 0,0213 degrés. Pour une lecture à bout de bras, 1px correspond donc à environ 0,26 mm (1/96 de pouce).

Dans 0,26 mm d'espace, nous pourrions avoir de très nombreux pixels réels.

Le navigateur le fait principalement pour des raisons héritées - la plupart des moniteurs étaient de 96 dpi lorsque le Web est né - mais aussi pour des raisons de cohérence, dans le «vieux temps», un bouton 22px sur un écran 15 pouces à 800x600 était deux fois plus grand qu'un bouton 22px sur un écran 15 pouces à 1600x1200. Dans ce cas, le DPI de l'écran est en fait 2x (deux fois la résolution horizontalement mais dans le même espace physique). C'est une mauvaise situation pour le Web et les applications, de sorte que la plupart des systèmes d'exploitation ont conçu de nombreuses façons d'abstraire les valeurs de pixels dans des unités indépendantes de l'appareil (DIPS sur Android, PT sur iOS et CSS Pixel sur le Web ).

Le navigateur iPhone Safari a été le premier (à ma connaissance) à introduire le concept de fenêtre d'affichage. Cela a été créé pour permettre aux applications de style bureau complet de s'afficher sur un petit écran. La fenêtre a été définie comme ayant une largeur de 960 pixels. Cela a essentiellement zoomé la page 3x (l'iphone était à l'origine de 320 pixels), donc 1 pixel CSS équivaut à 1/3 d'un pixel physique. Lorsque vous avez défini une fenêtre, vous pouvez faire en sorte que cet appareil corresponde à 1 pixel CSS = 1 pixel réel à 163 dpi.

En utilisant une fenêtre où la largeur est "largeur de l'appareil" vous évite d'avoir à définir la largeur de la fenêtre sur une base par appareil à la taille de pixel CSS optimale, le navigateur le fait juste pour vous.

Avec l'introduction des appareils à double DPI, les fabricants de téléphones mobiles ne voulaient pas que les pages mobiles paraissent 50% plus petites, ils ont donc introduit un concept appelé devicePixelRatio (d'abord sur le webkit mobile je crois), cela leur permet de garder 1 pixel CSS à peu près 1 / 96e de pouce, mais laissez-vous comprendre que vos éléments tels que les images peuvent avoir besoin d'une taille deux fois plus grande. Si vous regardez la série iPhone, tous leurs appareils disent que la largeur de l'écran en pixels CSS est de 320 pixels, même si nous savons que ce n'est pas vrai.

Par conséquent, si vous avez créé un bouton pour qu'il soit 22px dans l'espace CSS, la représentation sur l'écran physique est de 22 * ​​ratio de pixels de l'appareil. En fait, je dis ceci, ce n'est pas exactement cela parce que le rapport de pixels de l'appareil n'est jamais exact non plus, les fabricants de téléphones le définissent sur un bon nombre comme 2.0, 3.0 plutôt que 2.1329857289918 ....

En résumé, les pixels CSS sont indépendants de l'appareil et nous ne devons pas nous soucier des tailles physiques des écrans et des densités d'affichage, etc.

La morale de l'histoire est la suivante: ne vous inquiétez pas de comprendre la taille physique des pixels de l'écran. Vous n'en avez pas besoin. 50px devrait être à peu près le même sur tous les appareils mobiles, cela peut varier un peu, mais le CSS Pixel est notre moyen indépendant de l'appareil de créer des documents et des interfaces utilisateur cohérents.

Ressources:

Kinlan
la source
1
@matt il en sera de même sur les tablettes. Comme avec les livres Mac Retina. L'objectif est que le "pixel CSS" soit relativement uniforme sur toutes les plates-formes, surtout si vous définissez la largeur de la fenêtre = largeur de l'appareil.
Kinlan
14
Vous avez dit "vous ne pouvez rien faire avec eux". Je ne suis pas d'accord. Avec cette information , je serais en mesure de définir une police qui est toujours de 16 points (16 / 72nds d'un pouce dans le monde réel) de hauteur. C'est inestimable et c'est l'une des raisons pour lesquelles le développement natif continue d'être plus puissant que le développement Web.
trusktr
8
En fait, une utilisation parfaitement raisonnable de la taille réelle de l'écran en pixels est de rendre une image d'arrière-plan avec la résolution appropriée.
WhyNotHugo
2
"50px doit être à peu près le même sur tous les appareils mobiles", veuillez prouver qu'en utilisant par exemple un téléphone 1200x1920 4 pouces et une tablette 1000x600 10 pouces côte à côte.
iloveregex
6
Je ne suis pas non plus d'accord avec «vous ne pouvez rien faire avec eux»: vous pouvez détecter de manière fiable si l'appareil est un téléphone ou une tablette et supposer que l'utilisateur peut facilement pointer le dessus de l'écran avec son doigt ou non.
Brian Cannard
11

Sur la base de la réponse de Matt, j'ai fait un test:

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

Voici le résultat:

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

Nan.

Il ne semble donc pas encore possible d'obtenir de vraies valeurs physiques dans un navigateur Web.

trusktr
la source
Je ne suis pas sûr de la réponse à laquelle vous faites référence (je ne vois pas de "Matt" nulle part), mais j'obtiens NaN car svgEl.screenPixelToMillimeterXapparemment pas défini.
Michael
6

Vous pouvez créer n'importe quel élément de page et définir sa largeur à l'aide d'unités physiques réelles. Par exemple

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

Et puis obtenez sa largeur en pixels. Par exemple, le code html ci-dessous (j'ai utilisé JQuery) montre la largeur de l'écran de l'appareil en centimètres

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

alert(widthCM);
</script>
Mike
la source
Wow, je n'ai jamais réalisé que vous pouviez faire ça avec le CSS. À quel point est-ce exact? Comment votre navigateur connaît-il les dimensions physiques de votre écran? La compatibilité du navigateur pour cela sur caniuse.com est-elle quelque part? Je ne peux pas le trouver.
Jake Wilson
4
Le site du W3C déclare: «Dans le passé, CSS exigeait que les implémentations affichent correctement les unités absolues même sur les écrans d'ordinateur. Mais comme le nombre d'implémentations incorrectes dépassait les bonnes et que la situation ne semblait pas s'améliorer, CSS a abandonné cette exigence en 2011. Actuellement , les unités absolues ne doivent fonctionner correctement que sur la sortie imprimée et sur les périphériques haute résolution. CSS ne définit pas ce que signifie «haute résolution». Mais comme les imprimantes bas de gamme commencent aujourd'hui à 300 dpi et les écrans haut de gamme sont à 200 dpi, la coupure se situe probablement quelque part entre les deux. "
Mike
1
Je pense que le navigateur, comme toute autre application native, peut obtenir une résolution de périphérique via l'API du système d'exploitation, fournie au système d'exploitation par le pilote de périphérique. La précision dépend de ces informations.
Mike
Mais la résolution de l'appareil n'est pas la même que les dimensions physiques réelles. Un ordinateur portable 14 "et un ordinateur portable 15" peuvent avoir la même résolution.
Jake Wilson
6
Non! Vous ne pouvez pas. 10cm en Css auront une taille différente en réalité. C'est une pure question de chance s'il aura en fait 10 cm, 12 cm ou 7 cm. Voici ma démo de jsfiddle basée sur cette solution renvoyant des valeurs erronées, car les navigateurs se comportent toujours comme s'ils avaient des pixels par pouce (dpi): jsfiddle.net/Lzsm3zo9
Dariusz Sikorski
5

Vous pouvez obtenir ces informations avec WURFL:

Propriétés d'affichage de l'appareil

Les attributs sont appelés:

resolution_(width|height)

physical_display_(width|height)

Version longue:

La meilleure stratégie et la plus fiable pour y parvenir est d'envoyer le user agent stringdepuis le navigateur à une base de données comme WURFL(ou une autre) à jour qui peut fournir les informations nécessaires.

Chaîne de l'agent utilisateur

Il s'agit d'une information que tous les navigateurs modernes peuvent fournir; il expose des informations sur l'appareil et son système d'exploitation. Ce n'est tout simplement pas assez significatif pour votre application sans l'aide d'un dictionnaire comme WURFL.

WURFL

Il s'agit d'une base de données couramment utilisée pour détecter les propriétés des appareils.

Avec lui, vous pourrez peut-être prendre en charge avec précision la plupart des appareils populaires sur le marché. Je publierais une démo de code mais une est disponible en téléchargement sur le WURFLsite. Vous pouvez trouver une telle démo dans le dossier examples / demo qui est téléchargé avec la bibliothèque.

Télécharger WURFL

Voici plus d'informations et d'explications sur la vérification de la taille physique et de la résolution: http://www.scientiamobile.com/forum/viewtopic.php?f=16&t=286

AturSams
la source
3

En complément de la réponse «il n'y a pas de bonne solution à ce problème», il suffit de vérifier les unités que vous pouvez utiliser sur 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.

Avec cette description, il semble qu'il y ait une solution. cm, mmet inserait utilisé pour dessiner quelque chose avec la même taille indépendamment de la taille de l'écran et de la résolution. Dans cet esprit, vous pouvez vous attendre à ce qu'au moins l'un des px, ptou pcpuisse être utilisé pour dessiner au niveau du pixel, quelle que soit la précision que vous souhaitez utiliser (sinon, à quoi sert-il d'avoir des millions de pixels, non?). Et bien non. Toutes les unités sont des fractions d'une unité métrique, ce qui fait de toutes ces unités des échelles différentes. Et le pire dans l'histoire est le fait qu'aucune de celles-ci n'est exacte. Jouez simplement avec l'exemple w3schools (tracez une ligne de 20 cm et mesurez-la avec une règle).

Donc à la fin: - il n'y a aucun moyen de dessiner quelque chose avec des dimensions physiques avec précision ( ce qui devrait être le cas cm, mm, inet éventuellement ptet pc). - il n'y a aucun moyen de dessiner quelque chose avec la même taille indépendamment de la taille de l'écran et de la résolution (ce qui devrait être le cas au moins px).

C'est à la fois un problème de mise en œuvre (la taille réelle de l'écran n'est pas utilisée) et un problème de conception (pourquoi devrait pxêtre indépendant de la taille de l'écran alors qu'il y a déjà tellement d'unités pour cela).

À M
la source
2

J'ai abordé ce problème avec l'un de mes projets Web http://www.vinodiscover.com La réponse est que vous ne pouvez pas savoir avec certitude quelle est la taille physique, mais vous pouvez obtenir une approximation. En utilisant JS et / ou CSS, vous pouvez trouver la largeur et la hauteur de la fenêtre / de l'écran, ainsi que la densité de pixels à l'aide de requêtes multimédias. Par exemple: iPhone 5 (326 ppp) = 320px par 568px et une densité de 2,0 pixels, tandis qu'un Samsung Galaxy S4 (441ppi) = 360px x 640px et une densité de 3,0 pixels. En fait, une densité de 1,0 pixel est d'environ 150 ppp.

Compte tenu de cela, j'ai configuré mon CSS pour afficher 1 colonne lorsque la largeur est inférieure à 284px, quelle que soit la densité de pixels; puis deux colonnes entre 284px et 568px; puis 3 colonnes au-dessus de 852px. C'est beaucoup plus simple qu'il n'y paraît, puisque les navigateurs effectuent désormais automatiquement les calculs de densité de pixels.

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

Apollo Clark
la source
3
Dans le développement natif, vous pouvez obtenir la valeur exacte. +1 pour le natif, -1 pour le Web.
trusktr
Pouvez-vous obtenir la taille physique exacte sous Android?
Apollo Clark
2

En réponse à la réponse de zehelvion sur l'utilisation de WURFL pour trouver la résolution, il convient également de mentionner que WURFL est également disponible sous forme d' extrait de code JavaScript .

Dans l'édition gratuite proposée sur wurfl.io , vous n'obtiendrez pas d'informations sur l'écran et la résolution (uniquement le nom de l'appareil, le facteur de forme et mobile / non mobile), mais il existe également une version commerciale avec plus de capacités disponibles ici .

Jonarnes
la source
3
Je suggère que cela soit dans les commentaires sur cette réponse particulière.
darkgaze
1
c'est une solution ridiculement compliquée à quelque chose qui devrait simplement être fourni nativement par le navigateur.
Michael
2

Les pixels CSS ne sont pas vraiment notre "pixel indépendant de l'appareil". La plate-forme Web se compose de divers types d'appareils. Alors que le pixel CSS semble assez cohérent sur les ordinateurs de poche, il sera 50% plus grand sur un moniteur de bureau typique de 96 dpi. Voir ma question . Ce n'est vraiment pas une mauvaise chose dans certains cas, par exemple, les polices doivent être plus grandes sur un écran plus grand, car la distance à l'œil est plus grande. Mais les dimensions des éléments de l'interface utilisateur doivent être assez cohérentes. Disons que votre application a une barre supérieure, vous préférez qu'elle soit de la même épaisseur sur les ordinateurs de bureau et les mobiles, par défaut, elle sera 50% plus petite, ce qui n'est pas bon, car les éléments tactiles devraient être plus gros. La seule solution de contournement que j'ai trouvée consiste à appliquer différents styles en fonction du DPI du périphérique.

Vous pouvez obtenir le DPI d'écran en JavaScript avec window.devicePixelRatio. Ou requête 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*/
    }

Je ne sais pas comment cela fonctionnerait sur un moniteur de bureau à haute résolution. Les éléments seraient peut-être trop petits. C'est vraiment dommage que la plateforme web n'offre rien de mieux. Je suppose que la mise en œuvre de dip ne serait pas trop difficile.

Maciej Krawczyk
la source
non, vous ne pouvez pas. les requêtes des médias font cette stupide merde "supposer 96 dpi", c'est à dire qu'ils vous mentent sur ce qu'est le DPI lu.
Michael
1

J'ai remarqué dans vos commentaires que vous étiez en fait préoccupé par la taille des boutons, etc.

J'avais le même problème, jusqu'à ce que je découvre qu'il s'agissait simplement d'ajouter une balise meta à l'en-tête HTML pour définir l'échelle initiale:

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

Dan Kennedy
la source
0

JqueryMobile largeur de l'élément

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

JqueryMobile Hauteur de l'élément

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

Bonne chance Danny117

danny117
la source
3
Ce sont des dimensions virtuelles, qui ne sont pas toujours des dimensions physiques du monde réel.
trusktr
Merci je ne savais pas que
danny117
0

En utilisant la fonction getPPI () ( Web mobile: comment obtenir la taille physique des pixels? ), Pour obtenir un identifiant d'un pouce, utilisez cette formule:

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
la source
5
pourquoi pixelDepth?! pixelDepth n'est pas lié à la profondeur de couleur, auquel cas je me demande en quoi est-ce pertinent pour le calcul ici ....
matanster
0

J'aimerais pouvoir répondre à cela, mais les geeks qui créent des API ne fournissent pas les nécessités de base et les choses abstraites un peu trop parfois.

BTW J'ai 40 ans d'expérience en conception d'interface utilisateur et de conception de logiciels et j'ai insisté pour avoir exactement cela pour ce qui semble être une éternité depuis avant les jours des pilotes "VESA" :).

Pour l'écran tactile, j'avais un truc que j'appelais "fingerSize ()" qui était le nombre de pixels à 1cm (très proche du diamètre de la zone tactile moyenne du doigt) mais la donnée racine est "dpcm".

L'autre chose que vous voulez pour un écran est "l'angle de vue". Le type de dispositif d'affichage pour la visualisation et la fonction tactile définit à peu près la distance de visualisation.

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

C'est ce que nous essayons de fournir dans nos API mais hélas difficile à obtenir dans de nombreux cas.

Peterk
la source
-1

Vous pouvez obtenir une estimation approximative de la taille, mais ce n'est pas précis.

J'ai rassemblé un exemple que j'ai testé sur quelques appareils pour voir quels étaient les résultats. Mon iPhone 6 renvoie des valeurs environ 33% plus élevées. Mon moniteur de bureau de 27 "sur mon Mac est signalé comme un moniteur 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
la source
1
Mon 40 pouces signalé comme un 22 pouces.
RobotRock
Pas précis pour moi non plus. Je pense que le problème est dû à window.devicePixelRatio. C'est 1 sur un écran Apple Thunderbolt et 2 sur un Macbook Pro Touchbar 15 ". Cette valeur est-elle toujours un entier? Cela n'aurait pas de sens puisqu'il s'agit d'un ratio. Autres éléments: stackoverflow.com/questions/16385573/...
Tom