Canvas con DPI elevato

Paul Lewis

Introduzione

Gli schermi HiDPI sono fantastici, rendono tutto più fluido e pulito. Tuttavia, presentano anche una nuova serie di sfide per gli sviluppatori. In questo articolo esamineremo le sfide uniche del disegno di immagini nella tela nel contesto delle schermate HiDPI.

La proprietà devicePixelRatio

Cominciamo dall'inizio. Prima che fossero disponibili gli schermi HiDPI, un pixel era un pixel (se ignoriamo lo zoom e la scala per un attimo) e basta, non era necessario cambiare nulla. Se impostavi qualcosa su 100 pixel di larghezza, non c'era altro da fare. Poi sono comparsi i primi smartphone HiDPI con la proprietà leggermente enigmatica devicePixelRatio nell'oggetto window e disponibili per l'utilizzo nelle query sui media. Questa proprietà ci ha permesso di capire il rapporto tra il modo in cui i valori dei pixel (chiamati valori dei pixel logici) in CSS si traducono nel numero effettivo di pixel che il dispositivo userebbe per il rendering. Nel caso di un iPhone 4S, che ha un valore devicePixelRatio pari a 2, vedrai che un valore logico di 100 pixel corrisponde a un valore del dispositivo di 200 pixel.

Interessante, ma cosa significa per noi sviluppatori? All'inizio abbiamo notato che le nostre immagini venivano ridimensionate da questi dispositivi. Stavamo creando immagini con la larghezza in pixel logica dei nostri elementi e, quando venivano disegnate, venivano ridimensionate in base al valore devicePixelRatio e risultavano sfocate.

Un'immagine sottoposta a ridimensionamento e sfocatura a causa del valore devicePixelRatio
Figura 1: un'immagine viene ridimensionata e sfocata a causa del valore devicePixelRatio

La soluzione di fatto è stata creare immagini ridimensionate in base al valore devicePixelRatio e poi utilizzare il CSS per ridimensionarle nello stesso modo. Lo stesso vale per canvas.

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