Die HTML Canvas API ist eine JavaScript-Schnittstelle zum programmatischen, pixelbasierten Zeichnen auf einem <canvas>-Element im Browser – ohne DOM-Elemente, direkt auf Rasterebene.Was ist die Canvas API?
Das <canvas>-Element wurde mit HTML5 eingeführt und stellt eine zweidimensionale Zeichenfläche zur Verfügung. Im Gegensatz zu SVG, das vektorbasierte DOM-Elemente erzeugt, rendert Canvas direkt in einen Pixel-Puffer. Es gibt keinen „Szenegraph" – was gezeichnet wird, ist gezeichnet, nicht in einem Baum gespeichert.
Das macht Canvas ideal für:
- Animationen mit Hunderten oder Tausenden Elementen (Partikel, Sterne, Punkte)
- Generative Grafiken und algorithmische Kunst
- Bildverarbeitung (Filter, Effekte auf Bilder anwenden)
- Interaktive Visualisierungen (Zeichnen, Malen)
- Spiele (2D-Spiele im Browser)
Für komplexe 3D-Szenen nutzt man WebGL – Grundlagen für Kreative (WebGL) oder Three.js – 3D im Browser (Three.js als Abstraktion darüber).
Erklärung
Setup
``html <canvas id="meinCanvas" width="800" height="600"></canvas> ``
```javascript const canvas = document.getElementById('meinCanvas'); const ctx = canvas.getContext('2d');
// Responsives Canvas function canvasGroesseAnpassen() { canvas.width = window.innerWidth; canvas.height = window.innerHeight; } window.addEventListener('resize', canvasGroesseAnpassen); canvasGroesseAnpassen(); ```
Wichtig: Canvas-width und height sind die Pixel-Auflösung, nicht die CSS-Größe. Für Retina-Displays:
``javascript const dpr = window.devicePixelRatio || 1; canvas.width = window.innerWidth * dpr; canvas.height = window.innerHeight * dpr; canvas.style.width = window.innerWidth + 'px'; canvas.style.height = window.innerHeight + 'px'; ctx.scale(dpr, dpr); ``
Grundlegende Zeichenbefehle
```javascript // Rechteck ctx.fillStyle = '#0078ff'; ctx.fillRect(10, 10, 100, 60);
ctx.strokeStyle = '#333'; ctx.lineWidth = 2; ctx.strokeRect(10, 10, 100, 60);
// Kreis ctx.beginPath(); ctx.arc(200, 200, 50, 0, Math.PI * 2); ctx.fillStyle = 'rgba(255, 100, 0, 0.8)'; ctx.fill();
// Linie / Pfad ctx.beginPath(); ctx.moveTo(0, 0); ctx.lineTo(400, 300); ctx.quadraticCurveTo(200, 100, 400, 300); // Bézier-Kurve ctx.stroke();
// Text ctx.font = 'bold 48px Inter, sans-serif'; ctx.fillStyle = '#333'; ctx.fillText('Hallo Canvas', 100, 100); ```
Das Animations-Grundprinzip
Canvas-Animation funktioniert durch Wiederholen dieser drei Schritte:
- Löschen – Vorherigen Frame übermalen
- Zeichnen – Neuen Frame zeichnen
- Nächsten Frame anfragen –
requestAnimationFrame
```javascript function animationsLoop(zeitstempel) { // 1. Alles löschen ctx.clearRect(0, 0, canvas.width, canvas.height);
// 2. Frame zeichnen zeichneFrame(zeitstempel);
// 3. Nächsten Frame anfragen requestAnimationFrame(animationsLoop); }
// Loop starten requestAnimationFrame(animationsLoop); ```
requestAnimationFrame ist der optimale Weg für Browser-Animationen: Er synchronisiert mit der Bildwiederholrate des Monitors (meist 60Hz oder 120Hz) und pausiert automatisch, wenn der Tab nicht sichtbar ist.
Delta-Time für frame-rate-unabhängige Animation
```javascript let letzterZeitstempel = 0;
function animationsLoop(zeitstempel) { const delta = (zeitstempel - letzterZeitstempel) / 1000; // Sekunden letzterZeitstempel = zeitstempel;
ctx.clearRect(0, 0, canvas.width, canvas.height); aktualisiereObjekte(delta); // delta = Sekunden seit letztem Frame zeichneObjekte();
requestAnimationFrame(animationsLoop); } ```
Beispiele
Partikel-System
```javascript class Partikel { constructor() { this.zurücksetzen(); }
zurücksetzen() { this.x = Math.random() canvas.width; this.y = Math.random() canvas.height; this.vx = (Math.random() - 0.5) 2; // Geschwindigkeit X this.vy = (Math.random() - 0.5) 2; // Geschwindigkeit Y this.radius = Math.random() 3 + 1; this.lebensdauer = 1; // 0–1 this.verfall = Math.random() 0.01 + 0.005; }
aktualisieren(delta) { this.x += this.vx; this.y += this.vy; this.lebensdauer -= this.verfall; if (this.lebensdauer <= 0) this.zurücksetzen(); }
zeichnen(ctx) { ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2); ctx.fillStyle = rgba(0, 120, 255, ${this.lebensdauer}); ctx.fill(); } }
const partikel = Array.from({ length: 200 }, () => new Partikel());
function loop() { ctx.fillStyle = 'rgba(0, 0, 0, 0.05)'; // Langsam ausblendender Trail ctx.fillRect(0, 0, canvas.width, canvas.height);
partikel.forEach(p => { p.aktualisieren(); p.zeichnen(ctx); }); requestAnimationFrame(loop); }
requestAnimationFrame(loop); ```
Maus-interaktive Verbindungslinien
```javascript const punkte = []; const maus = { x: 0, y: 0 }; const maxAbstand = 120;
// Punkte erstellen for (let i = 0; i < 80; i++) { punkte.push({ x: Math.random() canvas.width, y: Math.random() canvas.height, vx: (Math.random() - 0.5) 0.5, vy: (Math.random() - 0.5) 0.5 }); }
canvas.addEventListener('mousemove', e => { maus.x = e.clientX; maus.y = e.clientY; });
function loop() { ctx.clearRect(0, 0, canvas.width, canvas.height);
punkte.forEach(p => { p.x += p.vx; p.y += p.vy; if (p.x < 0 || p.x > canvas.width) p.vx = -1; if (p.y < 0 || p.y > canvas.height) p.vy = -1;
// Punkt zeichnen ctx.beginPath(); ctx.arc(p.x, p.y, 2, 0, Math.PI * 2); ctx.fillStyle = '#0078ff'; ctx.fill();
// Linie zur Maus const abstandMaus = Math.hypot(maus.x - p.x, maus.y - p.y); if (abstandMaus < maxAbstand) { ctx.beginPath(); ctx.moveTo(p.x, p.y); ctx.lineTo(maus.x, maus.y); ctx.strokeStyle = rgba(0, 120, 255, ${1 - abstandMaus / maxAbstand}); ctx.stroke(); } });
requestAnimationFrame(loop); }
requestAnimationFrame(loop); ```
In der Praxis
Wann Canvas, wann SVG?
- Canvas für viele dynamische Objekte (>100 simultane Elemente)
- SVG für interaktive Einzelelemente mit DOM-Events
- Canvas für Bildmanipulation
- SVG für Animationen, die zugänglich sein müssen (Text in SVG ist zugänglich, Canvas ist blind für Screenreader)
Performance-Tipps:
ctx.save()/ctx.restore()für State-ManagementoffscreenCanvasfür aufwändige Berechnungen im WebWorker (Chrome 69+)- Nicht unnötig bei jedem Frame
clearRectüber die gesamte Fläche ausführen – nur dirty regions canvas.willReadFrequently = truewenn oftgetImageDatagerufen wird
Vergleich & Abgrenzung
| Canvas 2D | SVG Animationen | WebGL – Grundlagen für Kreative | |
|---|---|---|---|
| Typ | Raster | Vektor/DOM | Raster/GPU |
| Performance bei vielen Elementen | Gut | Schlecht | Sehr gut |
| DOM-Events | Manuell | Automatisch | Manuell |
| 3D | Nein | Begrenzt | Ja |
| Barrierefreiheit | Schlecht | Gut | Schlecht |
Häufige Fragen (FAQ)
Kann ich Canvas-Inhalte als Bild exportieren? Ja: canvas.toDataURL('image/png') oder canvas.toBlob(callback, 'image/jpeg', 0.9).
Warum ist mein Canvas unscharf auf Retina-Displays? Weil Canvas-Pixels physische Bildschirm-Pixels sind. Für Retina: Canvas mit devicePixelRatio multiplizieren (siehe Setup oben).
Wie mache ich Canvas barrierefrei? Alternativ-Inhalt im <canvas>-Tag einfügen. Für komplexe Visualisierungen: ARIA-Live-Regionen für Updates und textuelle Beschreibungen.
Verwandte Einträge
- WebGL – Grundlagen für Kreative – Wenn Canvas 2D nicht reicht (3D, Shader)
- Three.js – 3D im Browser – 3D im Browser auf Canvas-Basis
- Performance-Optimierung bei Web-Animationen – requestAnimationFrame und Performance
- SVG Animationen – Die DOM-basierte Alternative
Weiterführend
- MDN: Canvas API (2024) – developer.mozilla.org/Web/API/Canvas_API
- MDN: Canvas tutorial – developer.mozilla.org
- Eloquent JavaScript: Kapitel 17: Drawing on Canvas (Marijn Haverbeke, 2023)
- The Coding Train: Programming with p5.js – Youtube-Kanal von Daniel Shiffman
- Keith Peters: Foundation HTML5 Canvas (2011) – Apress
