web-dev-qa-db-fra.com

Détecter le système DPI/PPI de JS/CSS?

Je travaille sur une sorte d'application unique qui doit générer des images à des résolutions spécifiques en fonction du périphérique sur lequel elles sont affichées. La sortie est donc différente sur un navigateur Windows classique (96 ppp), un iPhone (163 ppp), Android G1 (180 ppp) et d'autres appareils. Je me demande s'il y a un moyen de détecter cela automatiquement.

Ma recherche initiale semble dire non. La seule suggestion que j’ai vue est de créer un élément dont la largeur est définie par "1in" en CSS, puis de vérifier son offsetWidth (voir aussi Comment accéder aux paramètres de résolution de l’affichage à l’écran via javascript? ). Cela a du sens, mais iPhone me ment avec cette technique, disant que c'est 96 ppp.

Une autre approche pourrait consister à obtenir les dimensions de l’affichage en pouces, puis à les diviser par la largeur en pixels, mais je ne suis pas sûr de savoir comment procéder non plus.

45
Josh Santangelo

Il existe la requête multimédia resolution CSS - elle vous permet de limiter les styles CSS à des résolutions spécifiques:

Cependant, il n’est supporté que par Firefox 3.5 et versions ultérieures, Opera 9 et versions ultérieures, et IE 9 . Les autres navigateurs n’appliqueront pas du tout vos styles spécifiques à la résolution (bien que je n’aie pas vérifié les navigateurs autres que les ordinateurs de bureau).

11
Paul D. Waite

<div id='testdiv' style='height: 1in; left: -100%; position: absolute; top: -100%; width: 1in;'></div>
<script type='text/javascript'>
  var devicePixelRatio = window.devicePixelRatio || 1;
  dpi_x = document.getElementById('testdiv').offsetWidth * devicePixelRatio;
  dpi_y = document.getElementById('testdiv').offsetHeight * devicePixelRatio;
  
  console.log(dpi_x, dpi_y);
</script>

attrapé à partir d'ici http://www.infobyip.com/detectmonitordpi.php . Fonctionne sur les appareils mobiles! (Android 4.2.2 testé)

10
MaxXx1313

Je suis venu avec un moyen qui ne nécessite pas le DOM ... du tout

Le DOM peut être compliqué, vous obligeant à ajouter des éléments au corps sans savoir ce qui se passe avec width: x !important dans votre feuille de style. Vous devez également attendre que le DOM soit prêt à être utilisé ...

// Binary search, (faster then loop)
// also don't test every possible value, since it tries low, mid, and high
// http://www.geeksforgeeks.org/find-the-point-where-a-function-becomes-negative/
function findFirstPositive(b, a, i, c) {
  c=(d,e)=>e>=d?(a=d+(e-d)/2,0<b(a)&&(a==d||0>=b(a-1))?a:0>=b(a)?c(a+1,e):c(d,a-1)):-1
  for (i = 1; 0 >= b(i);) i *= 2
  return c(i / 2, i)|0
}


var dpi = findFirstPositive(x => matchMedia(`(max-resolution: ${x}dpi)`).matches)

console.log(dpi)

8
Endless

Voici ce qui fonctionne pour moi (mais je ne l'ai pas testé sur les téléphones mobiles):

<body><div id="ppitest" style="width:1in;visible:hidden;padding:0px"></div></body>

Ensuite, je mets dans le .js: screenPPI = document.getElementById('ppitest').offsetWidth;

Cela m'a valu 96, ce qui correspond à la ppi de mon système.

6
john

J'avais également besoin d'afficher la même image avec la même taille à différents dpi d'écran, mais uniquement pour Windows IE. J'ai utilisé:

 <img src = "image.jpg" style = "
 hauteur: expression (scale (438, 192)); 
 width: expression (scale (270, 192))" />
 
 échelle de fonctions (x, dpi) {

 // dpi est pour les dimensions d'origine de l'image 
 renvoyer x * screen.deviceXDPI/dpi; 
} 

Dans ce cas, la largeur/hauteur de l'image d'origine est 270 et 438 et l'image a été développée sur un écran de 192 dpi. screen.deviceXDPI n'est pas défini dans Chrome et la fonction de balance devra être mise à jour pour prendre en charge les navigateurs autres que IE.

3
Farid Z
function getPPI(){
  // create an empty element
  var div = document.createElement("div");
  // give it an absolute size of one inch
  div.style.width="1in";
  // append it to the body
  var body = document.getElementsByTagName("body")[0];
  body.appendChild(div);
  // read the computed width
 var ppi = document.defaultView.getComputedStyle(div, null).getPropertyValue('width');
 // remove it again
 body.removeChild(div);
 // and return the value
 return parseFloat(ppi);

}

(De VodaFone)

2
TJS101

La réponse de @Endless est plutôt bonne, mais pas lisible du tout, C'est une approche similaire avec min/max fixe (ça devrait être bien)

var dpi = (function () {
    for (var i = 56; i < 2000; i++) {
        if (matchMedia("(max-resolution: " + i + "dpi)").matches === true) {
            return i;
        }
    }
    return i;
})();

matchMedia est maintenant bien pris en charge et devrait donner de bons résultats, voir http://caniuse.com/#feat=matchmedia

Attention, le navigateur ne vous donnera pas le dpi exact de l'écran mais seulement une approximation 

2
jrmgx

Je viens de trouver ce lien: http://dpi.lv/ . Il s'agit essentiellement d'un outil Web permettant de connaître la résolution de l'appareil client, les dpi et la taille de l'écran.

Je me suis rendu sur mon ordinateur et mon téléphone portable et il fournit la résolution et le DPI corrects pour moi. Il y a un repo github pour cela, vous pouvez donc voir comment cela fonctionne.

1
Adam

Le DPI est par définition lié à la taille physique de l'écran. Ainsi, vous ne pourrez pas avoir le vrai DPI sans connaître exactement le matériel derrière.

Les systèmes d’exploitation modernes ont convenu d’une valeur commune afin d’avoir des écrans compatibles: 96 dpi. C'est dommage mais c'est un fait.

Vous devrez vous fier au sniffing pour pouvoir deviner la taille réelle de l'écran nécessaire au calcul de la résolution (DPI = PixelSize/ScreenSize).

1
Vincent Robert

Je pense que votre meilleure approche consiste à combiner la suggestion de l'image "renifleur" avec une matrice de DPI connus pour les périphériques (via l'agent utilisateur et d'autres méthodes). Ce ne sera pas exact et ce sera difficile à maintenir, mais sans en savoir plus sur l'application que vous essayez de faire, c'est la meilleure suggestion que je puisse offrir.

1
FriendOfFuture

Générez une liste des DPI connus: https://stackoverflow.com/a/6793227

Détectez le périphérique exact. En utilisant quelque chose comme:

navigator.userAgent.toLowerCase();

Par exemple, lors de la détection de mobile:

window.isMobile=/iphone|iPod|ipad|Android|blackberry|opera mini|opera mobi|skyfire|maemo|windows phone|Palm|iemobile|symbian|symbianos|fennec/i.test(navigator.userAgent.toLowerCase());

Et profit!

0
haelmic

Tu ne peux rien faire d'autre? Par exemple, si vous générez une image devant être reconnue par une caméra (par exemple, si vous exécutez votre programme, passez votre téléphone portable sur une caméra, la magie opère), ne pouvez-vous pas utiliser un format indépendant de la taille?

S'il s'agit d'une application à déployer dans des environnements contrôlés, pouvez-vous fournir un utilitaire d'étalonnage? (vous pouvez faire quelque chose de simple, comme imprimer des cartes de visite avec une petite règle, l'utiliser pendant le processus de calibrage).

0
alex