Canvas mit hohem DPI-Wert

Paul Lewis

Einführung

HiDPI-Bildschirme sind toll, sie lassen alles flüssiger und übersichtlicher erscheinen. Sie stellen Entwickler jedoch 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.

Die Eigenschaft „devicePixelRatio“

Fangen wir am Anfang an. Bevor es HiDPI-Bildschirme gab, war ein Pixel ein Pixel (wenn wir Zoomen und Skalieren mal außer Acht lassen). Das war es dann auch schon. Sie mussten nichts weiter ändern. Wenn Sie etwas auf 100 Pixel Breite festgelegt haben, war das alles, was es gab. Dann kamen die ersten HiDPI-Mobilgeräte auf den Markt, die die etwas rätselhafte Property „devicePixelRatio“ auf dem Fensterobjekt hatten und für die Verwendung in Media-Queries verfügbar waren. Diese Eigenschaft ermöglichte uns, das Verhältnis zwischen Pixelwerten (logischer Pixelwert) und CSS zu verstehen, in dem sich beispielsweise CSS in die tatsächliche Anzahl von Pixeln übertragen, die das Gerät beim Rendern verwenden würde. Bei einem iPhone 4S mit einem devicePixelRatio von 2 entspricht ein logischer Wert von 100 Pixeln einem Gerätewert von 200 Pixeln.

Das ist interessant, aber was bedeutet das für uns Entwickler? Wir haben schnell gemerkt, dass unsere Bilder von diesen Geräten hochskaliert wurden. Wir erstellten Bilder in der logischen Pixelbreite unserer Elemente. Wenn sie herausgezogen wurden, wurden sie mit dem „devicePixelRatio“-Verhältnis vergrößert und verschwommen dargestellt.

Ein Bild, das aufgrund des devicePixelRatio hochskaliert und unscharf wird
Abbildung 1: Ein Bild, das aufgrund des devicePixelRatio hochskaliert und unscharf wird

Die de-facto-Lösung dafür bestand darin, Bilder zu erstellen, die um das devicePixelRatio vergrößert wurden, und sie dann mit CSS um denselben Betrag zu verkleinern. Das gilt auch 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();