Canvas mit hohem DPI-Wert

Paul Lewis

Einleitung

HiDPI-Bildschirme sind toll, damit alles glatter und sauberer aussieht. Sie stellen Entwickler aber auch vor neue Herausforderungen. In diesem Artikel sehen wir uns die besonderen Herausforderungen beim Zeichnen von Bildern auf dem Canvas im Kontext von HiDPI-Bildschirmen an.

Eigenschaft „devicePixelRatio“

Fangen wir am Anfang an. Früher gab es HiDPI-Bildschirme. Ein Pixel war ein Pixel (wenn wir das Zoomen und Skalieren ein wenig ignorieren) und das war es, dann brauchte man nichts weiter zu ändern. Bei einer Breite von 100 Pixeln war das alles. Dann tauchten die ersten HiDPI-Handys auf, und zwar mit der etwas rätselhaften devicePixelRatio-Eigenschaft im Fensterobjekt, die für die Verwendung in Medienabfragen zur Verfügung stand. Mithilfe dieser Eigenschaft konnten wir das Verhältnis der Pixelwerte (den wir logischen Pixelwert nennen) in CSS in die tatsächliche Anzahl von Pixeln übersetzen, die das Gerät beim Rendern verwenden würde. Im Fall eines iPhone 4S mit einem devicePixelRatio von 2 sehen Sie, dass der logische Wert 100 px einem Gerätewert von 200 px entspricht.

Das ist interessant, aber was bedeutet das für uns Entwickler? Ganz am Anfang haben wir alle bemerkt, dass unsere Bilder von diesen Geräten angepasst wurden. Wir erstellten Bilder mit der logischen Pixelbreite unserer Elemente. Wenn sie einmal gezeichnet waren, wurden sie mit dem Parameter „devicePixelRatio“ an die Größe angepasst und wären verschwommen.

Bild, das aufgrund von „devicePixelRatio“ vergrößert und verpixelt wird
Abbildung 1: Bild wird aufgrund von „devicePixelRatio“ skaliert und unkenntlich gemacht

Die De-facto-Lösung für dieses Problem bestand darin, Bilder zu erstellen, die um das GerätPixelRatio skaliert wurden, und dann CSS zu verwenden, um sie um den gleichen Wert zu verkleinern, und dasselbe gilt für 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();