Start · Sprachen · JavaScript · Referenz · CanvasRenderingContext2D.drawImage()

CanvasRenderingContext2D.drawImage()

Methode

Zeichnet ein Bild, ein Video, ein Canvas oder eine andere Bildquelle auf die Leinwand. Wahlweise wird es dabei skaliert oder nur ein Ausschnitt verwendet.

seit JavaScript Baseline: alle Browser Kategorie: webapi

Signatur

CanvasRenderingContext2D.prototype.drawImage(image, sx?, sy?, sWidth?, sHeight?, dx, dy, dWidth?, dHeight?)

Beschreibung

drawImage() ist die zentrale Methode, um Rastergrafiken in einen 2D-Canvas zu bringen. Als Quelle eignen sich HTMLImageElement, SVGImageElement, HTMLVideoElement (aktueller Frame), HTMLCanvasElement, OffscreenCanvas, ImageBitmap und VideoFrame.

Es gibt drei Aufrufformen:

  • drawImage(image, dx, dy) – zeichnet das Bild in Originalgröße an der Position (dx, dy).
  • drawImage(image, dx, dy, dWidth, dHeight) – zeichnet das Bild auf die angegebene Zielgröße skaliert.
  • drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight) – schneidet einen Ausschnitt (Quellrechteck) aus und zeichnet ihn in das Zielrechteck. Diese Form ist ideal für Sprite-Sheets, Zuschneiden und Zoomen.

Das Zeichnen berücksichtigt den aktuellen Zustand des Kontexts: Transformationen (translate, rotate, scale), globalAlpha, globalCompositeOperation, Clipping-Pfade, Filter und Schatten. Mit imageSmoothingEnabled legst du fest, ob beim Skalieren interpoliert wird. Das ist etwa für Pixel-Art wichtig.

Wichtig: Das Bild muss vollständig geladen sein. Ruft man drawImage() zu früh auf, passiert schlicht nichts, und es gibt auch keinen Fehler. Warte deshalb auf das load-Event oder auf image.decode().

Parameter

Name Typ Default Beschreibung
$image Pflicht HTMLImageElement | SVGImageElement | HTMLVideoElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap | VideoFrame Die Bildquelle, die gezeichnet werden soll.
$sx number 0 x-Koordinate der oberen linken Ecke des Quellausschnitts (nur in der 9-Argument-Form).
$sy number 0 y-Koordinate der oberen linken Ecke des Quellausschnitts (nur in der 9-Argument-Form).
$sWidth number Breite der Quelle Breite des Quellausschnitts.
$sHeight number Höhe der Quelle Höhe des Quellausschnitts.
$dx Pflicht number x-Koordinate im Canvas, an der das Bild gezeichnet wird.
$dy Pflicht number y-Koordinate im Canvas, an der das Bild gezeichnet wird.
$dWidth number sWidth bzw. natürliche Breite Breite des Bildes im Canvas. Bei Abweichung von der Quellbreite wird skaliert.
$dHeight number sHeight bzw. natürliche Höhe Höhe des Bildes im Canvas. Bei Abweichung von der Quellhöhe wird skaliert.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined).

Beispiele

Bild laden und in Originalgröße sowie skaliert zeichnen

const canvas = document.querySelector('#leinwand');
const ctx = canvas.getContext('2d');

const img = new Image();
img.src = '/bilder/logo.png';

// decode() wartet, bis das Bild zeichenbereit ist
await img.decode();

ctx.drawImage(img, 10, 10);            // Originalgröße
ctx.drawImage(img, 200, 10, 100, 50);  // auf 100×50 skaliert
console.log(`Gezeichnet: ${img.naturalWidth}×${img.naturalHeight}`);
Gezeichnet: 180×90

Sprite-Sheet: einzelnen Frame ausschneiden und animieren

const ctx = document.querySelector('canvas').getContext('2d');
const sprite = new Image();
sprite.src = '/bilder/held-lauf.png'; // 8 Frames à 64×64 nebeneinander

const FRAME = 64;
const FRAMES = 8;
let frame = 0;

const render = () => {
  ctx.clearRect(0, 0, 128, 128);
  ctx.imageSmoothingEnabled = false; // scharfe Pixel-Art
  ctx.drawImage(
    sprite,
    frame * FRAME, 0, FRAME, FRAME, // Quellausschnitt
    0, 0, 128, 128                  // Ziel: doppelte Größe
  );
  frame = (frame + 1) % FRAMES;
  setTimeout(() => requestAnimationFrame(render), 100);
};

sprite.addEventListener('load', render);

Video-Frame als Vorschaubild (Thumbnail) exportieren

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

video.addEventListener('seeked', () => {
  canvas.width = 320;
  canvas.height = Math.round(320 * video.videoHeight / video.videoWidth);
  ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
  const dataUrl = canvas.toDataURL('image/jpeg', 0.8);
  console.log(dataUrl.slice(0, 23));
}, { once: true });

video.currentTime = 5; // zu Sekunde 5 springen
data:image/jpeg;base64,

Bild zentriert und gedreht zeichnen

const ctx = document.querySelector('canvas').getContext('2d');
const img = new Image();
img.src = '/bilder/pfeil.png';
await img.decode();

const { width, height } = ctx.canvas;
ctx.save();
ctx.translate(width / 2, height / 2);
ctx.rotate(Math.PI / 4); // 45°
ctx.drawImage(img, -img.width / 2, -img.height / 2);
ctx.restore();

// Wichtig · Fallstricke

  • Ladezustand: Ein noch nicht geladenes Bild wird stillschweigend ignoriert. Nutze await img.decode() oder das load-Event. Ein Bild mit Status broken wirft einen InvalidStateError.
  • Tainted Canvas (CORS): Bilder von fremden Ursprüngen ohne CORS-Freigabe „verunreinigen“ den Canvas. Danach werfen getImageData(), toDataURL() und toBlob() einen SecurityError. Abhilfe: img.crossOrigin = 'anonymous' setzen, bevor src zugewiesen wird, und der Server muss Access-Control-Allow-Origin senden.
  • Argumentreihenfolge: In der 9-Argument-Form kommen die Quellkoordinaten (sx, sy, sWidth, sHeight) zuerst. Das ist ein häufiger Verwechslungsfehler.
  • Unschärfe: Auf hochauflösenden Bildschirmen (devicePixelRatio > 1) wirken Bilder verwaschen, wenn die interne Canvas-Größe nicht entsprechend hochskaliert wird. Nicht ganzzahlige Koordinaten führen ebenfalls zu Weichzeichnung.
  • Performance: Bei häufigem Zeichnen ist createImageBitmap() schneller, weil die Bilddaten bereits dekodiert vorliegen. Große SVG-Bilder bei jedem Frame neu zu rastern ist teuer.
  • Kompatibilität: Die Methode wird von allen Browsern unterstützt. VideoFrame und OffscreenCanvas als Quelle gibt es erst in neueren Browserversionen.