Canvas-Einführung
HTML <canvas>-Element: Koordinatensystem, 2D-Rendering-Kontext, High-DPI-Skalierung, Barrierefreiheit und ausführbare Zeichenbeispiele.
Das HTML <canvas>-Element ist eine rechteckige Zeichenfläche, die Sie vollständig per Skript steuern. Das Element selbst ist nur ein leerer Container — es zeichnet von sich aus nichts. Sie verwenden JavaScript, um Zeichenbefehle auszuführen, die Pixel darauf malen.
Diese Seite stellt das <canvas>-Element, sein Koordinatensystem, den 2D-Rendering-Kontext und die häufigsten Zeichenoperationen vor: Formen, Text, Farbverläufe, Linien und Bilder.
Was ist das <canvas>-Element?
<canvas> liefert Ihnen eine Bitmap — ein Pixelraster, in das Sie sofort zeichnen. Sobald eine Form gezeichnet wurde, erinnert sich das Canvas nicht mehr an sie als Objekt; es sind nur noch farbige Pixel. Das ist der entscheidende Unterschied zu SVG, wo jede Form als DOM-Knoten erhalten bleibt, den Sie einzeln neu gestalten oder animieren können.
Dieser Kompromiss bestimmt, wann Canvas die richtige Wahl ist:
- Wählen Sie
<canvas>für pixelgenaue Kontrolle, Tausende von Objekten, schnelle Frame-by-Frame-Animation, Spiele, Bildverarbeitung, datenreiche Diagramme oder Partikeleffekte. Da es sich um „Immediate-Mode"-Rendering handelt, ist das Neuzeichnen günstig. - Wählen Sie SVG, wenn Sie auflösungsunabhängige Vektoren, skalierbare Icons, eine überschaubare Anzahl von Formen brauchen, die Sie per CSS/DOM inspizieren, anklicken oder animieren möchten.
- Wählen Sie CSS für Layout, Übergänge und Effekte bei regulären HTML-Elementen — nicht für freies Zeichnen.
Sie können mehr als ein <canvas>-Element auf derselben HTML-Seite platzieren, jedes mit seinem eigenen Kontext.
Das Koordinatensystem
Ein Canvas verwendet ein zweidimensionales Koordinatengitter. Der Ursprung (0, 0) liegt in der oberen linken Ecke. Die x-Achse wächst nach rechts, die y-Achse wächst nach unten — beachten Sie, dass y nach unten wächst, entgegen einem mathematischen Koordinatensystem. Ein Punkt (100, 60) liegt demnach 100 Pixel vom linken Rand und 60 Pixel vom oberen Rand entfernt.
Der Zeichenbereich wird durch die Attribute width und height (in CSS-Pixeln) festgelegt:
<canvas id="canvas" width="250" height="150"></canvas>Legen Sie die Canvas-Größe mit den Attributen width und height fest, nicht per CSS. CSS width/height streckt lediglich die vorhandene Bitmap, was Ihre Zeichnung unscharf werden lässt. Fügen Sie einen Rahmen über das style-Attribut oder eine Klasse hinzu.
Der 2D-Rendering-Kontext
Sie zeichnen nie direkt auf dem <canvas>-Element — Sie zeichnen über einen Rendering-Kontext, ein Objekt, das die Zeichen-API bereitstellt. Sie erhalten ihn mit getContext():
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');getContext('2d') gibt ein CanvasRenderingContext2D zurück, das alle weiter unten verwendeten Methoden und Eigenschaften enthält (fillRect, arc, fillText, strokeStyle usw.). Es ist der richtige Einstiegspunkt für nahezu jede 2D-Zeichnung.
Weitere Kontexttypen gibt es für andere Zwecke:
'webgl'/'webgl2'— GPU-beschleunigtes 3D (und hochperformantes 2D) über die OpenGL ES API.'bitmaprenderer'— zeigt einImageBitmapohne eigene Zeichen-API an.
Dieses Kapitel verwendet ausschließlich den '2d'-Kontext.
Barrierefreiheit: Fallback-Inhalt
Alles, was Sie zwischen dem öffnenden und dem schließenden <canvas>-Tag platzieren, ist Fallback-Inhalt. Browser, die Canvas unterstützen, ignorieren ihn; Browser (oder Hilfstechnologien), die das Canvas nicht rendern können, zeigen ihn stattdessen an. Da die gezeichneten Pixel für Screenreader unsichtbar sind, nutzen Sie diesen Platz, um die Grafik zu beschreiben, oder fügen Sie ein aria-label / role hinzu, damit das Canvas sinnvoll angekündigt wird.
<canvas id="canvas" width="250" height="150" role="img" aria-label="A blue circle on a white background">
A blue circle on a white background.
</canvas>Bei interaktiven Canvases (Spiele, Zeichen-Apps) stellen Sie echte fokussierbare HTML-Steuerelemente innerhalb des Elements als Fallback bereit, da die Pixel selbst nicht per Tastatur erreichbar sind.
Beispiel des HTML <canvas>-Tags:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="canvas" width="250" height="150" style="border:1px solid #1c87c9;">
The HTML5 canvas tag is not supported by your browser.
</canvas>
</body>
</html>Beispiel des HTML <canvas>-Tags zum Zeichnen eines Kreises:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="exampleCanvas" width="200" height="200" style="border:1px solid #dddddd;">
HTML5 canvas tag is not supported by your browser.
</canvas>
<script>
const c = document.getElementById("exampleCanvas");
const ctx = c.getContext("2d");
ctx.beginPath();
ctx.arc(100, 100, 60, 0, 2 * Math.PI);
ctx.strokeStyle = '#009299';
ctx.stroke();
</script>
</body>
</html>Die Methode arc() nimmt fünf Argumente: arc(x, y, radius, startAngle, endAngle). Dabei ist (100, 100) der Mittelpunkt des Kreises, 60 der Radius in Pixeln, und der Bogen verläuft vom Winkel 0 bis 2 * Math.PI. Winkel werden in Radiant gemessen, ein vollständiger Kreis entspricht 2π Radiant, sodass 0 bis 2 * Math.PI den kompletten Kreis zeichnet. beginPath() beginnt einen neuen Pfad, und stroke() zeichnet seine Kontur mit dem aktuellen strokeStyle. Um ihn stattdessen zu füllen, setzen Sie fillStyle und rufen fill() auf. Mehr dazu unter Canvas-Zeichnen und Canvas-Koordinaten.
Beispiel des HTML <canvas>-Tags zum Zeichnen von Text:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="exampleCanvas" width="350" height="110" style="border:1px solid #dddddd;">
HTML5 canvas tag is not supported by your browser.
</canvas>
<script>
const c = document.getElementById("exampleCanvas");
const ctx = c.getContext("2d");
ctx.font = "40px Arial";
ctx.fillStyle = '#262ac7';
ctx.fillText("Canvas Text", 55, 65);
</script>
</body>
</html>fillText(text, x, y) malt gefüllten Text an den angegebenen Koordinaten. Die Eigenschaft font verwendet die Standard-CSS-Schriftart-Kurzschreibweise. Siehe Canvas-Text für Ausrichtung, Textumrisse und Breitenmessung.
Beispiel des HTML <canvas>-Tags zum Zeichnen eines linearen Farbverlaufs:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="exampleCanvas" width="300" height="140" style="border:1px solid #dddddd;">
The HTML5 canvas tag is not supported by your browser.
</canvas>
<script>
const c = document.getElementById("exampleCanvas");
const ctx = c.getContext("2d");
const grd = ctx.createLinearGradient(0, 0, 300, 0);
grd.addColorStop(0, "#359900");
grd.addColorStop(1, "#ffffff");
ctx.fillStyle = grd;
ctx.fillRect(20, 20, 250, 100);
</script>
</body>
</html>createLinearGradient(x0, y0, x1, y1) definiert die Richtung des Farbverlaufs durch zwei Punkte. Hier verläuft (0, 0) bis (300, 0) als horizontaler Verlauf von links nach rechts. addColorStop(offset, color) setzt eine Farbe an einer Position von 0 (Anfang) bis 1 (Ende), sodass Grün in Weiß übergeht. Das Zuweisen des Verlaufs zu fillStyle bewirkt, dass fillRect(x, y, width, height) damit malt. Mehr dazu unter Canvas-Farbverläufe.
Beispiel des HTML <canvas>-Tags zum Zeichnen einer Linie:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="exampleCanvas" width="150" height="150" style="border:1px solid #cccccc;">
The HTML5 canvas tag is not supported by your browser.
</canvas>
<script>
const c = document.getElementById("exampleCanvas");
const ctx = c.getContext("2d");
ctx.moveTo(0, 0);
ctx.lineTo(150, 150);
ctx.strokeStyle = '#86417d';
ctx.stroke();
</script>
</body>
</html>moveTo(x, y) hebt den „Stift" an einen Startpunkt, ohne zu zeichnen, und lineTo(x, y) fügt ein gerades Segment bis zu diesem Punkt hinzu. Erst wenn Sie stroke() aufrufen, wird etwas sichtbar. Siehe Canvas-Zeichnen für mehrsegmentige Pfade, Linienbreite und Verbindungsarten.
Beispiel des HTML <canvas>-Tags zum Zeichnen eines Bildes:
Um in sich geschlossen zu bleiben (und Cross-Origin-Probleme zu vermeiden — siehe Hinweis unten), verwendet dieses Beispiel ein kleines eingebettetes SVG-Bild als Data-URI statt eines Remote-Fotos:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<h2>Draw an image with canvas</h2>
<canvas id="exampleCanvas" width="220" height="120" style="border:1px solid #dddddd;"></canvas>
<script>
const canvas = document.getElementById('exampleCanvas');
const ctx = canvas.getContext('2d');
const image = new Image();
image.addEventListener('load', () => {
// drawImage(image, dx, dy) draws at the given top-left position
ctx.drawImage(image, 10, 10);
// Scaled copy: drawImage(image, dx, dy, dWidth, dHeight)
ctx.drawImage(image, 120, 10, 50, 50);
});
image.src =
"data:image/svg+xml," +
encodeURIComponent(
'<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">' +
'<circle cx="50" cy="50" r="45" fill="#1c87c9" /></svg>'
);
</script>
</body>
</html>drawImage() akzeptiert drei Formen: drawImage(image, dx, dy), drawImage(image, dx, dy, dWidth, dHeight) zum Skalieren, und drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight) zum Ausschneiden eines Quell-Rechtecks (s*) und Platzieren in einem Ziel-Rechteck (d*). Zeichnen Sie immer innerhalb des load-Events des Bildes, damit die Pixel bereit sind. Weitere Informationen unter Canvas-Bilder.
CORS-Fallstrick. Das Zeichnen eines Bildes von einer anderen Origin ohne korrekte CORS-Header „verunreinigt" das Canvas. Danach werfen getImageData() und toDataURL() einen Sicherheitsfehler. Wenn Sie Pixel von einem Remote-Bild auslesen möchten, muss das Bild mit permissiven CORS-Headern bereitgestellt und mit image.crossOrigin = "anonymous" geladen werden, bevor src gesetzt wird.
Beispiel des HTML <canvas>-Tags zum Zeichnen eines kreisförmigen Farbverlaufs:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="exampleCanvas" width="260" height="160" style="border:1px solid #cdcdcd;">
The HTML5 canvas tag is not supported by your browser.
</canvas>
<script>
const c = document.getElementById("exampleCanvas");
const ctx = c.getContext("2d");
const grd = ctx.createRadialGradient(150, 75, 10, 115, 90, 150);
grd.addColorStop(0, "purple");
grd.addColorStop(1, "white");
ctx.fillStyle = grd;
ctx.fillRect(20, 20, 220, 120);
</script>
</body>
</html>createRadialGradient(x0, y0, r0, x1, y1, r1) mischt zwischen zwei Kreisen: einem Startkreis (Mittelpunkt (150, 75), Radius 10) und einem Endkreis (Mittelpunkt (115, 90), Radius 150). Die Farbstopps verlaufen von Lila beim inneren Kreis bis Weiß beim äußeren, was den runden Leuchthalo erzeugt. Vergleichen Sie mit createLinearGradient oben und lesen Sie mehr unter Canvas-Farbverläufe.
High-DPI-(Retina-)Displays
Auf hochauflösenden Bildschirmen entspricht ein CSS-Pixel mehreren Gerätepixeln. Ein Canvas, das nur in CSS-Pixeln skaliert ist, wirkt auf solchen Displays daher unscharf. Die Lösung besteht darin, die Bitmap um window.devicePixelRatio zu skalieren und anschließend den Kontext zu skalieren, sodass Ihre Zeichenkoordinaten gleich bleiben:
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const ratio = window.devicePixelRatio || 1;
// CSS size (layout) stays the same:
const cssWidth = 250;
const cssHeight = 150;
canvas.style.width = cssWidth + 'px';
canvas.style.height = cssHeight + 'px';
// Backing bitmap gets more device pixels:
canvas.width = cssWidth * ratio;
canvas.height = cssHeight * ratio;
// Scale once so you keep drawing in CSS-pixel coordinates:
ctx.scale(ratio, ratio);Danach erzeugt das Zeichnen von arc(100, 100, 60, …) einen gestochen scharfen Kreis sowohl auf Standard- als auch auf Retina-Displays.
Verwandte Kapitel
- Canvas-Zeichnen — Pfade, Rechtecke, Füllungen und Konturen
- Canvas-Text — Schriften, Ausrichtung und Textmessung
- Canvas-Koordinaten — das Raster, Verschieben und Drehen
- Canvas-Farbverläufe — lineare und radiale Farbmischungen
- Canvas-Bilder — Zeichnen und Bearbeiten von Bitmaps
- Canvas-Referenz — vollständige Liste der Kontext-Methoden und -Eigenschaften