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

CanvasRenderingContext2D.bezierCurveTo()

Methode

Fügt dem aktuellen Unterpfad eine kubische Bézier-Kurve mit zwei Kontrollpunkten vom aktuellen Punkt bis zum Endpunkt <code>(x, y)</code> hinzu.

seit JavaScript Baseline: alle Browser Kategorie: webapi

Signatur

CanvasRenderingContext2D.prototype.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)

Beschreibung

bezierCurveTo() erweitert den aktuellen Pfad um eine kubische Bézier-Kurve. Die Kurve beginnt am aktuellen Punkt des Pfades (zuletzt gesetzt z. B. über moveTo(), lineTo() oder eine vorherige Kurve), endet im Punkt (x, y) und wird von den zwei Kontrollpunkten (cp1x, cp1y) und (cp2x, cp2y) „angezogen“. Die Kurve läuft in der Regel nicht durch die Kontrollpunkte – sie bestimmen nur die Tangenten an Start und Ende.

Die Methode eignet sich für weiche, organische Formen: Herzen, Wellen, Sprechblasen, Verbindungslinien in Diagrammen (Node-Editoren) oder geglättete Linienzüge in Charts. Im Gegensatz zu quadraticCurveTo() mit nur einem Kontrollpunkt erlaubt die kubische Variante S-Kurven und eine unabhängige Steuerung von Anfangs- und Endrichtung.

Wie alle Pfadmethoden zeichnet bezierCurveTo() selbst nichts sichtbar. Erst ein Aufruf von stroke() oder fill() rendert den Pfad. Nach dem Aufruf ist (x, y) der neue aktuelle Punkt, sodass sich mehrere Kurven nahtlos verketten lassen.

Parameter

Name Typ Default Beschreibung
$cp1x Pflicht number x-Koordinate des ersten Kontrollpunkts (bestimmt die Richtung am Startpunkt).
$cp1y Pflicht number y-Koordinate des ersten Kontrollpunkts.
$cp2x Pflicht number x-Koordinate des zweiten Kontrollpunkts (bestimmt die Richtung am Endpunkt).
$cp2y Pflicht number y-Koordinate des zweiten Kontrollpunkts.
$x Pflicht number x-Koordinate des Endpunkts; wird zum neuen aktuellen Punkt.
$y Pflicht number y-Koordinate des Endpunkts.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined). Der Pfad wird direkt verändert.

Beispiele

Einfache S-Kurve zeichnen

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

ctx.beginPath();
ctx.moveTo(20, 100);               // Startpunkt
ctx.bezierCurveTo(
  80, 10,                          // Kontrollpunkt 1
  160, 190,                        // Kontrollpunkt 2
  230, 100                         // Endpunkt
);
ctx.lineWidth = 3;
ctx.strokeStyle = '#0a7';
ctx.stroke();

Herzform aus zwei Kurven füllen

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

ctx.beginPath();
ctx.moveTo(100, 60);
ctx.bezierCurveTo(100, 30, 50, 30, 50, 65);
ctx.bezierCurveTo(50, 100, 100, 120, 100, 150);
ctx.bezierCurveTo(100, 120, 150, 100, 150, 65);
ctx.bezierCurveTo(150, 30, 100, 30, 100, 60);
ctx.closePath();
ctx.fillStyle = 'crimson';
ctx.fill();

Verbindungslinie zwischen zwei Knoten (Node-Editor)

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

const connect = (from, to) => {
  // Horizontale Tangenten für weiche Kabel-Optik
  const dx = Math.abs(to.x - from.x) * 0.5;
  ctx.beginPath();
  ctx.moveTo(from.x, from.y);
  ctx.bezierCurveTo(from.x + dx, from.y, to.x - dx, to.y, to.x, to.y);
  ctx.stroke();
};

ctx.strokeStyle = '#333';
ctx.lineWidth = 2;
connect({ x: 40, y: 40 }, { x: 260, y: 160 });
connect({ x: 40, y: 160 }, { x: 260, y: 40 });

Kontrollpunkte zur Fehlersuche sichtbar machen

const ctx = document.querySelector('canvas').getContext('2d');
const start = { x: 30, y: 150 }, cp1 = { x: 90, y: 20 }, cp2 = { x: 200, y: 20 }, end = { x: 260, y: 150 };

ctx.beginPath();
ctx.moveTo(start.x, start.y);
ctx.bezierCurveTo(cp1.x, cp1.y, cp2.x, cp2.y, end.x, end.y);
ctx.stroke();

// Hilfslinien und Punkte
ctx.setLineDash([4, 4]);
ctx.strokeStyle = 'gray';
ctx.beginPath();
ctx.moveTo(start.x, start.y); ctx.lineTo(cp1.x, cp1.y);
ctx.moveTo(end.x, end.y); ctx.lineTo(cp2.x, cp2.y);
ctx.stroke();
ctx.setLineDash([]);

ctx.fillStyle = 'red';
[cp1, cp2].forEach(({ x, y }) => ctx.fillRect(x - 3, y - 3, 6, 6));

// Wichtig · Fallstricke

  • Fehlender Startpunkt: Gibt es keinen aktuellen Punkt (z. B. direkt nach beginPath() ohne moveTo()), setzt der Browser implizit (cp1x, cp1y) als Startpunkt – das ergibt meist eine unerwartete Kurve. Daher immer vorher moveTo() aufrufen.
  • Nicht-endliche Werte: Ist ein Argument NaN oder Infinity, wird der Aufruf still ignoriert – es gibt keinen Fehler. Berechnete Koordinaten also vorher prüfen.
  • Kontrollpunkte liegen nicht auf der Kurve: Die Kurve verläuft innerhalb der konvexen Hülle aus Start-, Kontroll- und Endpunkt, berührt die Kontrollpunkte aber im Allgemeinen nicht.
  • Glatte Übergänge: Für knickfreie Verkettung muss der zweite Kontrollpunkt einer Kurve, der gemeinsame Endpunkt und der erste Kontrollpunkt der nächsten Kurve auf einer Geraden liegen.
  • Transformationen: Die Koordinaten werden durch die aktuelle Transformationsmatrix (translate(), scale(), rotate()) umgerechnet.
  • Die Methode gibt es auch auf Path2D und OffscreenCanvasRenderingContext2D; sie wird von allen modernen Browsern seit Jahren unterstützt.