HTML5 Mobile

Retina-Display: HTML-Canvas optimieren

Viele HTML-Elemente von mobilen Websites werden automatisch auf Geräten mit Retina-Display optimal dargestellt. Nicht jedoch das canvas-Element.

Das HTML-Element canvas (vom engl. Wort für Leinwand) ist eine Fläche, auf der mit JavaScript gezeichnet werden. So werden beispielweise Grafiken, Linien, Kreise, Bèzierkurven oder Farbverläufe unterstützt. Wie auch Website-Bilder (PNG, JPG) für das Retina-Display optimiert werden müssen, so ist dies auch für canvas-Elemente auf iOS-Geräten erforderlich.

Es folgt ein Überblick, wie man das Canvas-Element für iOS optimiert — und dabei auch bereits die neuen MacBooks mit Retina-Display berücksichtigt.

Optimale Darstellung, wenn Canvas-Pixel = Device-Pixel

Wie bereits im Artikel Unterschiede zwischen CSS-, Bild- und Device-Pixel erklärt, ist es wichtig, dass die Bild- und Device-Pixel übereinstimmen. Man muss also dafür sorgen, dass die Größe des Canvas (= Bild-Pixel) mit dem Display übereinstimmt. Konkret bedeutet dies, dass der Canvas z.B. statt 320x240px eine Auflösung von 640x480px besitzen muss, um scharf auszusehen.

Unterschiede zwischen nicht-optimiertem Canvas (oben) und Optimierung.

Unterschiede zwischen iOS und OS X

Ein wichtiger Unterschied zwischen iOS und Mac OS X liegt darin, dass OS X diese Pixelverdopplung des Canvas automatisch erledigt. Auf einem Desktop ist genügend Leistung vorhanden, so dass ohne jegliche Veränderung des Website-Codes automatisch alle Canvas-Elemente auf einem neuen Macbook mit Retina Display scharf sind.

Auf mobilen Endgeräten soll der Website-Entwickler jedoch aus Performance-Gesichtpunkten selbst entscheiden können, ob er die Verdopplung der Auflösung (= 4-fache Anzahl an Pixeln) anbieten möchte oder nicht.

Daraus ergibt sich folgende Aufgabe:

  1. Herausfinden, ob es sich um ein Retina-Display handelt oder nicht.
  2. Herausfinden, ob es der Canvas bereits vom Betriebssystem verdoppelt wird oder nicht. Wenn ja, dann darf nichts mehr verdoppelt werden (sonst erhielte man die 4-fache Canvas-Größe). Wenn nein, muss die Canvas-Größe verdoppelt werden.

Canvas

Retina-Display erkennen (windows.devicePixelRatio)

Als erstes stellt sich die Frage, woran erkennt mit die Devices mit hochauflösendem Bildschirm? Dies lässt sich in JavaScript über die Eigenschaft windows.devicePixelRatio herausfinden.

Automatische Pixel-Verdopplung bei Canvas erkennen (context.webkitBackingStorePixelRatio)

Im Anschluss muss geprüft werden, ob die Canvas-Pixel vom Betriebssystem bereits verdoppelt werden. Hier gibt es eine neue Eigenschaft (var ctx = canvas.getContext('2d'); ctx.webkitBackingStorePixelRatio ).

devicePixelRatio und webkitBackingStorePixelRatio

Beispiele

Das erste Beispiel dient zur Betrachtung auf einem iPhone mit Retina-Display. Es zeigt lediglich die Unterschiede, zwischen einem nicht-optimierten und einem optimierten Canvas-Element (Screenshot siehe oben).

Wie man die beiden Erkennungen (Retina-Display und automatische Verdopplung) nun als generische Lösung implementieren kann, zeigt das zweite Beispiel. Auf diese Weise wird die Canvas-Verdopplung nur auf iOS-Geräten mit Retina-Display durchgeführt, auf anderen Geräten und Desktop-Rechner nicht.

if (canvas.getContext) {
 var ctx = canvas.getContext('2d');
 
 var factor = 1;
 
 // retina display?
 var isRetina = (window.devicePixelRatio > 1);
 
 // iOS? (-> no auto double)
 var isIOS = ((ctx.webkitBackingStorePixelRatio < 2) || (ctx.webkitBackingStorePixelRatio == undefined));
 
 if (isRetina && isIOS) {
  factor = 2;	
 }		
 
 canvas.setAttribute('width', 350*factor);
 canvas.setAttribute('height', 120*factor);
 ctx.scale(factor, factor);

4 Kommentare zu: Retina-Display: HTML-Canvas optimieren

Carl M.
2. August 2012, 08:12

Guter Artikel, aber ist das ein reiner Apple-Blog? Retina ist doch lediglich Apples Marketingbegriff für hochauflösende Dispays, aber die gibts ja nun nicht nur bei Apple.

flo
2. August 2012, 20:32

Klar, aber aufgrund der hohen Verbreitung hat das iPhone eine gewisse Relevanz und bietet sich für solche Erläuterungen gut an, da viele dies dann auch selbst nachvollziehen und ausprobieren können.

dave
30. Mai 2014, 14:46

Hallo,

der Artikel ist jetzt schon etwas älter, steht aber bei der Google-Suche „canvas retina“ weit oben. Ich habe für mein kleines Projekt folgendes zusammengeschustert:

var canvas = document.getElementById(„logo“);
var ctx = canvas.getContext(„2d“);

if (window.devicePixelRatio) {
var devicePixelRatio = window.devicePixelRatio;
var canvasWidth = canvas.getAttribute(„width“);
var canvasHeight = canvas.getAttribute(„height“);

canvas.style.width = canvasWidth+“px“;
canvas.style.height = canvasHeight+“px“;
canvas.setAttribute(„width“, canvasWidth*devicePixelRatio);
canvas.setAttribute(„height“, canvasHeight*devicePixelRatio);
ctx.transform(devicePixelRatio,0,0,devicePixelRatio,0,0);
}

Obwohl es wahrscheinlich nicht die perfekteste Lösung ist, funktioniert es soweit ganz gut bei mir.

Hoppe
12. August 2016, 14:46

window.devicePixelRatio, nicht windows.devicePixelRatio

Obacht hier, hat nichts mit Windows zu tun!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

*

*