Detectando o sistema DPI / PPI de JS / CSS?

Estou trabalhando em um tipo de aplicativo exclusivo que precisa gerar imagens em resoluções específicas de acordo com o dispositivo em que elas são exibidas. Portanto, a saída é diferente em um navegador normal do Windows (96ppi), iPhone (163ppi), Android G1 (180ppi) e outros dispositivos. Eu estou querendo saber se há uma maneira de detectar isso automaticamente.

Minha pesquisa inicial parece dizer não. A única sugestão que eu vi é fazer um elemento cuja largura é especificada como “1in” em CSS, então verifique seu offsetWidth (veja também Como acessar as configurações de DPI da canvas via javascript? ). Faz sentido, mas o iPhone está mentindo para mim com essa técnica, dizendo que é 96ppi.

Outra abordagem pode ser obter as dimensões da exibição em polegadas e depois dividir pela largura em pixels, mas também não sei como fazer isso.

 

Eu inventei uma maneira que não requer o DOM …

O DOM pode ser confuso, exigindo que você acrescente coisas ao corpo sem saber o que está acontecendo com a width: x !important em sua folha de estilo. Você também teria que esperar que o DOM estivesse pronto para usar …

 // 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+(ed)/2,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) 

Aqui está o que funciona para mim (mas não testei em telefones celulares):

 

Então eu coloco no .js: screenPPI = document.getElementById('ppitest').offsetWidth;

Isso me deu 96, o que corresponde ao ppi do meu sistema.

Eu também precisava exibir a mesma imagem no mesmo tamanho em diferentes dpi de canvas, mas apenas para o Windows IE. Eu usei:

 

 escala de funções (x, dpi) {

     // dpi é para dimensões originais da imagem
     return x * screen.deviceXDPI / dpi;
 }

Neste caso, a largura / altura da imagem original são 270 e 438 e a imagem foi desenvolvida na canvas de 192dpi. O screen.deviceXDPI não está definido no Chrome, e a function de escala precisa ser atualizada para oferecer suporte a navegadores diferentes do IE

 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)

A resposta de @Endless é muito boa, mas não é legível, é uma abordagem similar com min / max fixo (deve ser bom)

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

matchMedia agora é bem suportado e deve dar um bom resultado, veja http://caniuse.com/#feat=matchmedia

Tenha cuidado, o navegador não lhe dará o dpi exato da canvas, mas apenas uma aproximação

Acho que sua melhor abordagem é combinar a sugestão da imagem “sniffer” com uma matriz de DPIs conhecidos para dispositivos (via agente do usuário e outros methods). Não será exato e será uma tarefa difícil de manter, mas sem saber mais sobre o aplicativo que você está tentando criar, essa é a melhor sugestão que posso oferecer.

O DPI está, por definição, vinculado ao tamanho físico da exibição. Então você não poderá ter o DPI real sem saber exatamente o hardware por trás.

Os sistemas operacionais modernos concordam com um valor comum para ter canvass compatíveis: 96 dpi. Isso é uma pena, mas isso é um fato.

Você terá que confiar no sniffing para poder adivinhar o tamanho real da canvas necessário para calcular a resolução (DPI = PixelSize / ScreenSize).

Acabei de encontrar este link: http://dpi.lv/ . Basicamente, é um webtool para descobrir a resolução do dispositivo do cliente, o dpi e o tamanho da canvas.

Eu visitei no meu computador e telefone celular e fornece a resolução correta e DPI para mim. Existe um repo do github para você, assim você pode ver como funciona.

Você não pode fazer mais nada? Por exemplo, se você está gerando uma imagem para ser reconhecida por uma câmera (ou seja, você executa seu programa, passa seu celular pela câmera, a mágica acontece), você não pode usar algo independente do tamanho?

Se este é um aplicativo a ser implantado em ambientes controlados, você pode fornecer um utilitário de calibração? (Você pode fazer algo simples como imprimir cartões de visita com uma régua pequena, usá-lo durante o processo de calibração).

Gere uma lista de DPI conhecidos: https://stackoverflow.com/a/6793227

Detectar o dispositivo exato. Usando algo como:

 navigator.userAgent.toLowerCase(); 

Por exemplo, ao detectar dispositivos móveis:

 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()); 

E lucro!