Tela com DPI alto

Introdução

As telas HiDPI são lindas, elas fazem tudo parecer mais suave e limpo. Mas eles também apresentam um novo conjunto de desafios para os desenvolvedores. Neste artigo, vamos analisar os desafios específicos de desenhar imagens na tela no contexto de telas HiDPI.

A propriedade devicePixelRatio

Vamos começar do início. Antes das telas HiDPI, um pixel era um pixel (se ignorarmos o zoom e o dimensionamento), e só isso, não era preciso mudar nada. Se você definir uma largura de 100px, isso é tudo. Em seguida, os primeiros celulares HiDPI começaram a aparecer com a propriedade devicePixelRatio ligeiramente enigmática no objeto de janela e disponível para uso em consultas de mídia. Com essa propriedade, conseguimos entender a proporção de como os valores de pixels (que chamamos de valor de pixel lógico) em, por exemplo, o CSS se traduziria no número real de pixels que o dispositivo usaria ao renderizar. No caso de um iPhone 4S, que tem um devicePixelRatio de 2, um valor lógico de 100 px equivale a um valor de dispositivo de 200 px.

A informação é interessante, mas o que isso significa para nós, desenvolvedores? Bem, nos primeiros dias, todos nós começamos a perceber que nossas imagens estavam sendo aprimoradas por esses dispositivos. Estávamos criando imagens com a largura lógica de pixel dos nossos elementos e, quando elas eram desenhadas, elas seriam aumentadas pelo devicePixelRatio e estariam borrados.

Uma imagem sendo ampliada e desfocada devido ao dispositivoPixelRatio
Figura 1: uma imagem sendo ampliada e desfocada devido ao dispositivoPixelRatio

A solução real para isso foi criar imagens redimensionadas pelo devicePixelRatio e usar CSS para reduzi-las na mesma quantidade, e o mesmo vale para telas.

function setupCanvas(canvas) {
  // Get the device pixel ratio, falling back to 1.
  var dpr = window.devicePixelRatio || 1;
  // Get the size of the canvas in CSS pixels.
  var rect = canvas.getBoundingClientRect();
  // Give the canvas pixel dimensions of their CSS
  // size * the device pixel ratio.
  canvas.width = rect.width * dpr;
  canvas.height = rect.height * dpr;
  var ctx = canvas.getContext('2d');
  // Scale all drawing operations by the dpr, so you
  // don't have to worry about the difference.
  ctx.scale(dpr, dpr);
  return ctx;
}

// Now this line will be the same size on the page
// but will look sharper on high-DPI devices!
var ctx = setupCanvas(document.querySelector('.my-canvas'));
ctx.lineWidth = 5;
ctx.beginPath();
ctx.moveTo(100, 100);
ctx.lineTo(200, 200);
ctx.stroke();