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 nel canvas nel contesto degli schermi HiDPI.

La proprietà devicePixelRatio

Iniziamo dall'inizio. Prima di avere schermi HiDPI, un pixel era un pixel (se ignoriamo per un attimo lo zoom e la scalabilità) e non era necessario modificare nulla. Se impostavi la larghezza di un elemento su 100 px, non c'era altro da fare. Poi sono apparsi i primi dispositivi mobili HiDPI con la proprietà devicePixelRatio, leggermente enigmatica, sull'oggetto window e disponibile per l'uso nelle query supporti. Questa proprietà ci ha permesso di capire il rapporto tra i valori dei pixel (che chiamiamo valore dei pixel logici) in, ad esempio, CSS e il numero effettivo di pixel che il dispositivo avrebbe utilizzato per il rendering. Nel caso di un iPhone 4S, che ha un devicePixelRatio di 2, vedrai che un valore logico di 100 px equivale a un valore del dispositivo di 200 px.

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

Un'immagine viene ridimensionata e sfocata a causa di devicePixelRatio
Figura 1 - Un'immagine viene ridimensionata e sfocata a causa di devicePixelRatio

La soluzione di fatto è stata quella di creare immagini ingrandite in base al devicePixelRatio e poi utilizzare il CSS per ridurle della stessa quantità, e lo stesso vale per il 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();