Signatur
Beschreibung
Mit scale() änderst du das Koordinatensystem des Canvas-Kontexts. Standardmäßig entspricht eine Einheit genau einem Pixel. Nach ctx.scale(2, 2) ist jede Einheit zwei Pixel groß. Ein Rechteck mit fillRect(10, 10, 50, 50) wird dann ab Position (20, 20) mit 100 × 100 Pixeln gezeichnet. Skaliert werden die Koordinaten und auch Linienstärken, Schriftgrößen und Schattenversätze.
Die Skalierung kommt zusätzlich zur bestehenden Transformation hinzu, d. h. die aktuelle Matrix wird mit ihr multipliziert. Zwei Aufrufe von scale(2, 2) ergeben also eine Skalierung um den Faktor 4. Deshalb setzt man scale() meist zusammen mit save() und restore() ein oder setzt die Matrix mit setTransform() bzw. resetTransform() gezielt zurück.
Typische Einsatzfälle sind:
- scharfe Darstellung auf HiDPI-/Retina-Displays mit
window.devicePixelRatio, - Zoomfunktionen in Zeichen- und Kartenanwendungen,
- Spiegeln von Grafiken oder Text mit negativen Faktoren wie
scale(-1, 1).
Die Skalierung geht immer vom Ursprung (0, 0) des aktuellen Koordinatensystems aus. Soll um einen anderen Punkt skaliert werden, verschiebst du den Ursprung zuerst mit translate() dorthin, skalierst und verschiebst dann wieder zurück.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $x Pflicht | number | Skalierungsfaktor in horizontaler Richtung. 1 lässt die Breite unverändert, Werte über 1 vergrößern, Werte zwischen 0 und 1 verkleinern und negative Werte spiegeln an der y-Achse. |
|
| $y Pflicht | number | Skalierungsfaktor in vertikaler Richtung. Negative Werte spiegeln an der x-Achse. |
Rückgabewert
undefined). Die Methode verändert nur die Transformationsmatrix des Kontexts.Beispiele
Einfache Skalierung eines Rechtecks
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
// Ohne Skalierung
ctx.fillStyle = 'steelblue';
ctx.fillRect(10, 10, 40, 20);
ctx.save();
ctx.scale(3, 2); // x × 3, y × 2
ctx.fillStyle = 'tomato';
ctx.fillRect(10, 20, 40, 20); // landet bei (30, 40) mit 120 × 40 px
ctx.restore();
console.log(ctx.getTransform().a, ctx.getTransform().d);
Scharfes Canvas auf HiDPI-Displays
const setupHiDPICanvas = (canvas, cssWidth, cssHeight) => {
const dpr = window.devicePixelRatio || 1;
canvas.width = Math.round(cssWidth * dpr);
canvas.height = Math.round(cssHeight * dpr);
canvas.style.width = `${cssWidth}px`;
canvas.style.height = `${cssHeight}px`;
const ctx = canvas.getContext('2d');
ctx.scale(dpr, dpr); // ab jetzt in CSS-Pixeln zeichnen
return ctx;
};
const ctx = setupHiDPICanvas(document.querySelector('#chart'), 300, 150);
ctx.font = '16px sans-serif';
ctx.fillText('Gestochen scharf', 20, 40);
Text horizontal spiegeln
const ctx = document.querySelector('canvas').getContext('2d');
ctx.save();
ctx.scale(-1, 1); // Spiegelung an der y-Achse
ctx.font = '32px serif';
// x-Koordinate negativ angeben, damit der Text sichtbar bleibt
ctx.fillText('Spiegelschrift', -250, 50);
ctx.restore();
Zoom um einen beliebigen Punkt (z. B. Mausposition)
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
let zoom = 1;
const draw = (cx, cy) => {
ctx.setTransform(1, 0, 0, 1, 0, 0); // Matrix zurücksetzen
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.translate(cx, cy); // Ursprung zum Zoompunkt
ctx.scale(zoom, zoom);
ctx.translate(-cx, -cy); // zurückverschieben
ctx.strokeRect(50, 50, 100, 100);
};
canvas.addEventListener('wheel', (event) => {
event.preventDefault();
zoom *= event.deltaY < 0 ? 1.1 : 0.9;
draw(event.offsetX, event.offsetY);
}, { passive: false });
draw(0, 0);
// Wichtig · Fallstricke
- Skalierungen summieren sich: Jeder Aufruf multipliziert die bestehende Matrix. Nach
scale(2, 2)undscale(0.5, 0.5)hast du wieder den Faktor 1. Zwei Aufrufe mit 2 ergeben aber 4. Mitsave()/restore()odersetTransform()behältst du den Überblick. - Linienstärke wird mitskaliert: Nach
scale(5, 1)sind senkrechte Linien fünfmal so dick wie waagerechte. Eine gleichmäßige Linie erreichst du, wenn du den Pfad bei aktiver Skalierung erzeugst undstroke()erst nachrestore()aufrufst. - Faktor 0: Mit
scale(0, …)wird die Matrix singulär, danach wird nichts mehr sichtbar gezeichnet. AuchNaNoderInfinityals Argument haben keine Wirkung: Der Aufruf wird ohne Fehlermeldung ignoriert. - Die Reihenfolge zählt:
translate()und dannscale()liefert ein anderes Ergebnis als die umgekehrte Reihenfolge, weil die Verschiebung beim zweiten Fall mitskaliert wird. - HiDPI: Wenn du
canvas.widthodercanvas.heightneu setzt, wird der Kontext samt Transformation zurückgesetzt.scale(dpr, dpr)musst du danach erneut aufrufen. - Kompatibilität: Wird von allen modernen Browsern unterstützt, auch von
OffscreenCanvasRenderingContext2Din Web Workern.