Das waren schon immer Sie, Canvas2D.

Krajeski
Aaron Krajeski

In einer Welt der Shader, Meshes und Filter kann Canvas2D Sie vielleicht nicht begeistern. Aber es sollte! 30–40% der Webseiten haben ein <canvas>-Element und 98% aller Canvases verwenden einen Canvas2D-Renderingkontext. Es gibt Canvas2Ds in Autos, Kühlschränken und im Weltraum.

Zugegebenermaßen ist die API bei hochmodernen 2D-Zeichnungen etwas hinterher. Glücklicherweise haben wir hart an der Implementierung neuer Funktionen in Canvas2D gearbeitet, um CSS auf den neuesten Stand zu bringen, die Ergonomie zu optimieren und die Leistung zu verbessern.

Teil 1: Informationen zu CSS

In CSS gibt es einige Zeichenbefehle, die in Canvas2D so kaum fehlen. Die neue API hat einige der am häufigsten gewünschten Funktionen hinzugefügt:

Rechteckiges abgerundetes Rechteck

Abgerundete Rechtecke: der Eckpfeiler des Internets, der nahen Computerverarbeitung und der Zivilisation.

Generell sind abgerundete Rechtecke äußerst nützlich: als Schaltflächen, Sprechblasen, Miniaturansichten, Sprechblasen einfach. Es war schon immer möglich, ein abgerundetes Rechteck in Canvas2D zu erstellen, aber die Sache war etwas unübersichtlich:

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'magenta';

const top = 10;
const left = 10;
const width = 200;
const height = 100;
const radius = 20;

ctx.beginPath();
ctx.moveTo(left + radius, top);
ctx.lineTo(left + width - radius, top);
ctx.arcTo(left + width, top, left + width, top + radius, radius);
ctx.lineTo(left + width, top + height - radius);
ctx.arcTo(left + width, top + height, left + width - radius, top + height, radius);
ctx.lineTo(left + radius, top + height);
ctx.arcTo(left, top + height, left, top + height - radius, radius);
ctx.lineTo(left, top + radius);
ctx.arcTo(left, top, left + radius, top, radius);
ctx.stroke();

All dies war für ein einfaches, einfaches abgerundetes Rechteck erforderlich:

Ein abgerundetes Rechteck

Die neue API bietet die Methode roundRect().

ctx.roundRect(upper, left, width, height, borderRadius);

Das Obige kann also vollständig ersetzt werden durch:

ctx.roundRect(10, 10, 200, 100, 20);

Die Methode ctx.roundRect() verwendet auch ein Array für das borderRadius-Argument mit bis zu vier Zahlen. Mit diesen Radien werden die vier Ecken des abgerundeten Rechtecks genauso gesteuert wie CSS. Beispiel:

ctx.roundRect(10, 10, 200, 100, [15, 50, 30]);

Sieh dir die Demo an und probier alles aus.

Kegelverlauf

Sie kennen lineare Farbverläufe:

const gradient = ctx.createLinearGradient(0, 0, 200, 100);
gradient.addColorStop(0, 'blue');
gradient.addColorStop(0.5, 'magenta');
gradient.addColorStop(1, 'white');
ctx.fillStyle = gradient;
ctx.fillRect(10, 10, 200, 100);

Ein linearer Farbverlauf.

Radiale Farbverläufe:

const radialGradient = ctx.createRadialGradient(150, 75, 10, 150, 75, 70);
radialGradient.addColorStop(0, 'white');
radialGradient.addColorStop(0.5, 'magenta');
radialGradient.addColorStop(1, 'lightblue');

ctx.fillStyle = radialGradient;
ctx.fillRect(0, 0, canvas.width, canvas.height);

Ein radialer Farbverlauf.

Aber wie sieht es mit einem schönen Kegelverlauf aus?

const grad = ctx.createConicGradient(0, 100, 100);

grad.addColorStop(0, 'red');
grad.addColorStop(0.25, 'orange');
grad.addColorStop(0.5, 'yellow');
grad.addColorStop(0.75, 'green');
grad.addColorStop(1, 'blue');

ctx.fillStyle = grad;
ctx.fillRect(0, 0, 200, 200);

Ein kegelförmiger Farbverlauf.

Textmodifikatoren

Die Text-Rendering-Funktionen von Canvas2D sind knifflig. Chrome hat dem Canvas2D-Text-Rendering mehrere neue Attribute hinzugefügt:

Alle diese Attribute entsprechen den Preisvergleichsportal-Gegenstücken mit demselben Namen.

Teil 2: Ergonomische Optimierungen

Zuvor waren einige Dinge mit Canvas2D möglich, aber unnötig kompliziert zu implementieren. Hier sind einige Verbesserungen der Lebensqualität für JavaScript-Entwickler, die Canvas2D verwenden möchten:

Kontext zurückgesetzt

Um das Löschen eines Canvas zu erklären, habe ich eine alberne kleine Funktion zum Zeichnen eines Retro-Musters geschrieben:

draw90sPattern();

Ein Retromuster aus Dreiecken und Quadraten.

Sehr gut! Jetzt, da ich mit diesem Muster fertig bin, möchte ich den Canvas leeren und etwas anderes zeichnen. Moment mal, wie löschen wir einen Canvas wieder? Yeah! Natürlich ctx.clearRect().

ctx.clearRect(0, 0, canvas.width, canvas.height);

Hm... das hat nicht funktioniert. Yeah! Dazu muss ich zuerst die Transformation zurücksetzen:

ctx.resetTransform();
ctx.clearRect(0, 0, canvas.width, canvas.height);
Eine leere Leinwand.

Super! Eine schöne leere Leinwand. Zeichnen wir nun eine schöne horizontale Linie:

ctx.moveTo(10, 10);
ctx.lineTo(canvas.width, 10);
ctx.stroke();

Eine horizontale und eine diagonale Linie.

Grrrr! Das ist nicht richtig! 😡 Was macht die zusätzliche Linie hier? Warum ist es rosa? Okay, sehen wir uns mal StackOverflow an.

canvas.width = canvas.width;

Warum ist das so albern? Warum ist das so schwierig?

Das ist nicht mehr der Fall. Die neue API bietet einfache, elegante und bahnbrechende Funktionen:

ctx.reset();

Es tut mir leid, dass es so lange gedauert hat.

Filter

SVG-Filter sind eine Welt für sich. Wenn Sie neu bei Ihnen sind, empfehle ich Ihnen das folgende Video: The Art Of SVG Filters And Why It Is Awesome, das Ihnen ihr unglaubliches Potenzial zeigt.

SVG-Stilfilter sind bereits für Canvas2D verfügbar. Sie müssen lediglich bereit sein, den Filter als URL zu übergeben, die auf ein anderes SVG-Filterelement auf der Seite verweist:

<svg>
  <defs>
    <filter id="svgFilter">
      <feGaussianBlur in="SourceGraphic" stdDeviation="5" />
      <feConvolveMatrix kernelMatrix="-3 0 0 0 0.5 0 0 0 3" />
      <feColorMatrix type="hueRotate" values="90" />
    </filter>
  </defs>
</svg>
const canvas = document.createElement('canvas');
canvas.width = 500;
canvas.height = 400;
const ctx = canvas.getContext('2d');
document.body.appendChild(canvas);

ctx.filter = "url('#svgFilter')";
draw90sPattern(ctx);

Das bringt unser Muster ziemlich gut durch:

Das Retromuster mit einem weichgezeichneten Effekt.

Aber was tun Sie, wenn Sie die obigen Schritte ausführen möchten, aber innerhalb von JavaScript bleiben und nicht mit Zeichenfolgen herumspielen möchten? Mit der neuen API ist das absolut möglich.

ctx.filter = new CanvasFilter([
  { filter: 'gaussianBlur', stdDeviation: 5 },
  {
    filter: 'convolveMatrix',
    kernelMatrix: [
      [-3, 0, 0],
      [0, 0.5, 0],
      [0, 0, 3],
    ],
  },
  { filter: 'colorMatrix', type: 'hueRotate', values: 90 },
]);

Kinderleicht! Probieren Sie es aus und spielen Sie die Parameter in dieser Demo ab.

Teil 3: Leistungsverbesserungen

Mit der neuen Canvas2D API wollten wir außerdem die Leistung verbessern. Wir haben einige Funktionen hinzugefügt, um Entwicklern eine genauere Kontrolle ihrer Websites zu ermöglichen und raffinierte Framerates zu ermöglichen:

Häufig gelesen

Verwenden Sie getImageData(), um Pixeldaten aus einem Canvas zurückzulesen. Sie kann sehr langsam sein. Mit der neuen API können Sie einen Canvas explizit zum Zurücklesen markieren (z. B. für generative Effekte). Auf diese Weise können Sie alles im Hintergrund optimieren und Canvas für eine Vielzahl von Anwendungsfällen schnell halten. Diese Funktion ist seit einiger Zeit in Firefox verfügbar und wird nun in die Canvas-Spezifikation integriert.

const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d', { willReadFrequently: true });

Kontextverlust

Lass uns wieder traurige Registerkarten glücklich machen! Für den Fall, dass einem Client der GPU-Arbeitsspeicher ausgeht oder Ihr Canvas aus einem anderen Katastrophenfall stößt, können Sie jetzt einen Callback empfangen und nach Bedarf neu zeichnen:

const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');

canvas.addEventListener('contextlost', onContextLost);
canvas.addEventListener('contextrestored', redraw);

Wenn Sie mehr über Canvas-Kontext und Verlust erfahren möchten, finden Sie im Wiki der whatWG eine gute Erklärung.

Fazit

Ganz gleich, ob Sie Canvas2D zum ersten Mal verwenden, es schon seit Jahren verwenden oder es seit Jahren vermeiden – ich zeige Ihnen, wie Sie Canvas neu gestalten können. Es ist die API von nebenan, die es schon immer gegeben hat.

Danksagungen

Hero-Image von Sandie Clarke auf Unsplash