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

CanvasRenderingContext2D.save()

Methode

Legt den aktuellen Zeichenzustand des 2D-Kontexts (Transformation, Clipping, Stile) auf einen internen Stapel, damit er später mit <code>restore()</code> wiederhergestellt werden kann.

seit JavaScript Baseline: alle Browser Kategorie: webapi

Signatur

CanvasRenderingContext2D.prototype.save()

Beschreibung

save() speichert den gesamten Zeichenzustand eines CanvasRenderingContext2D und legt ihn auf einen Stapel (Stack). Mit restore() wird der zuletzt gespeicherte Zustand wieder vom Stapel genommen und aktiviert. So lassen sich Transformationen oder Stiländerungen vorübergehend anwenden, ohne sie danach einzeln zurücksetzen zu müssen.

Zum gespeicherten Zustand gehören unter anderem:

  • die aktuelle Transformationsmatrix (translate(), rotate(), scale(), setTransform())
  • der aktuelle Clipping-Bereich (clip())
  • die Strichmuster-Liste (setLineDash()) und lineDashOffset
  • Eigenschaften wie fillStyle, strokeStyle, globalAlpha, globalCompositeOperation, lineWidth, lineCap, lineJoin, miterLimit, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, font, textAlign, textBaseline, direction, imageSmoothingEnabled, filter und weitere

Nicht gespeichert werden der aktuelle Pfad (beginPath(), moveTo() usw.) und die bereits gezeichneten Pixel – save() ist also kein Schnappschuss der Grafik, sondern nur der Einstellungen. Für Pixeldaten nutzt man getImageData().

Typischer Einsatz: Bevor man ein einzelnes Objekt gedreht, verschoben oder mit Clipping zeichnet, ruft man save() auf, zeichnet und ruft danach restore() auf. Aufrufe dürfen verschachtelt werden; jedes save() sollte ein passendes restore() haben.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined).

Beispiele

Stil temporär ändern und wiederherstellen

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

ctx.fillStyle = 'steelblue';
ctx.save(); // Zustand mit blauer Füllfarbe sichern

ctx.fillStyle = 'tomato';
ctx.fillRect(10, 10, 100, 100); // rotes Quadrat

ctx.restore(); // wieder blau
ctx.fillRect(130, 10, 100, 100); // blaues Quadrat
console.log(ctx.fillStyle);
#4682b4

Gedrehtes Objekt zeichnen, ohne die Transformation zu verschleppen

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

const drawRotatedBox = (x, y, size, angle) => {
  ctx.save();
  ctx.translate(x + size / 2, y + size / 2); // Ursprung in die Mitte
  ctx.rotate(angle);
  ctx.fillStyle = 'seagreen';
  ctx.fillRect(-size / 2, -size / 2, size, size);
  ctx.restore(); // Transformation und Farbe zurücksetzen
};

drawRotatedBox(20, 20, 60, Math.PI / 4);
drawRotatedBox(120, 20, 60, Math.PI / 8);
// Folgende Zeichnungen sind wieder unverändert:
ctx.strokeRect(220, 20, 60, 60);

Clipping begrenzen – nur mit save/restore aufhebbar

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

ctx.save();
ctx.beginPath();
ctx.arc(100, 100, 50, 0, Math.PI * 2);
ctx.clip(); // Ab jetzt nur noch im Kreis zeichnen
ctx.fillStyle = 'gold';
ctx.fillRect(0, 0, 200, 200); // erscheint als Kreis
ctx.restore(); // Clipping-Bereich aufgehoben

ctx.fillStyle = 'purple';
ctx.fillRect(160, 160, 60, 60); // wieder überall sichtbar

Verschachtelte Zustände in einer Animationsschleife

const ctx = document.querySelector('canvas').getContext('2d');
let angle = 0;

const frame = () => {
  ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
  ctx.save();                 // Ebene 1: Mittelpunkt
  ctx.translate(150, 150);
  ctx.rotate(angle);
  ctx.fillRect(-40, -5, 80, 10);

  ctx.save();                 // Ebene 2: Satellit
  ctx.translate(60, 0);
  ctx.rotate(angle * 3);
  ctx.fillStyle = 'crimson';
  ctx.fillRect(-10, -10, 20, 20);
  ctx.restore();              // zurück zu Ebene 1

  ctx.restore();              // zurück zum Ausgangszustand
  angle += 0.02;
  requestAnimationFrame(frame);
};
requestAnimationFrame(frame);

// Wichtig · Fallstricke

  • Immer paarweise verwenden: Jedes save() braucht ein passendes restore(). Fehlt es (z. B. durch einen frühen return oder eine Ausnahme), wächst der Stapel in Animationsschleifen immer weiter und Transformationen stapeln sich unerwartet. Bei Bedarf try…finally nutzen.
  • Der Pfad wird nicht gespeichert: Nach restore() ist der aktuelle Pfad unverändert – rufen Sie beginPath() explizit auf.
  • Pixel werden nicht gesichert: restore() macht keine Zeichenoperationen rückgängig.
  • restore() auf leerem Stapel bewirkt nichts (kein Fehler).
  • Performance: save()/restore() kopiert den kompletten Zustand. Wenn nur die Transformation zurückgesetzt werden muss, ist setTransform(1, 0, 0, 1, 0, 0) bzw. resetTransform() oft günstiger. Clipping lässt sich dagegen nur über restore() (oder reset()) aufheben.
  • Das Setzen von canvas.width/height oder ctx.reset() leert den Zustandsstapel vollständig.
  • Kompatibilität: in allen Browsern unterstützt, ebenso in OffscreenCanvasRenderingContext2D (Web Worker).