CanvasRenderingContext2D: arcTo()-Methode

Baseline Widely available

This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.

Die CanvasRenderingContext2D.arcTo()-Methode der Canvas 2D API fügt dem aktuellen Unterpfad einen Kreisbogen hinzu, unter Verwendung der angegebenen Kontrollpunkte und des Radius. Der Bogen wird gegebenenfalls automatisch mit einer Geraden mit dem neuesten Punkt des Pfads verbunden, z. B. wenn der Startpunkt und die Kontrollpunkte auf einer Linie liegen.

Diese Methode wird häufig verwendet, um abgerundete Ecken zu erstellen.

Hinweis: Sie können unerwartete Ergebnisse erzielen, wenn Sie einen relativ großen Radius verwenden: Die Verbindungsgerade des Bogens wird sich in die Richtung orientieren, die erforderlich ist, um den angegebenen Radius zu erreichen.

Syntax

js
arcTo(x1, y1, x2, y2, radius)

Parameter

x1

Die x-Koordinate des ersten Kontrollpunkts.

y1

Die y-Koordinate des ersten Kontrollpunkts.

x2

Die x-Koordinate des zweiten Kontrollpunkts.

y2

Die y-Koordinate des zweiten Kontrollpunkts.

radius

Der Radius des Bogens. Muss nicht-negativ sein.

Nutzungshinweise

Angenommen, P0 ist der Punkt auf dem Pfad, wenn arcTo() aufgerufen wird, P1 = (x1, y1) und P2 = (x2, y2) sind die ersten und zweiten Kontrollpunkte bzw., und r ist der im Aufruf angegebene radius:

  • Wenn r negativ ist, wird eine IndexSizeError- Ausnahme ausgelöst.
  • Wenn r 0 ist, verhält sich arcTo() so, als ob P0, P1 und P2 kollinear (auf einer Linie) sind.
  • Im Falle, dass alle Punkte kollinear sind, wird eine Linie von P0 zu P1 gezeichnet, es sei denn, die Punkte P0 und P1 sind identisch (haben die gleichen Koordinaten), in diesem Fall wird nichts gezeichnet.

Diese Bedingungen können im Beispiel Konstruktion eines arcTo()-Pfades unten erstellt werden, um die Ergebnisse zu sehen.

Rückgabewert

Keiner (undefined).

Ausnahmen

IndexSizeError DOMException

Wird ausgelöst, wenn radius einen negativen Wert hat.

Beispiele

Funktionsweise von arcTo()

Eine Möglichkeit, über arcTo() nachzudenken, besteht darin, sich zwei gerade Abschnitte vorzustellen: einen vom Startpunkt zu einem ersten Kontrollpunkt und einen weiteren von dort zu einem zweiten Kontrollpunkt. Ohne arcTo() würden diese beiden Abschnitte eine scharfe Ecke bilden: arcTo() erzeugt einen kreisförmigen Bogen an dieser Ecke und glättet sie aus. Mit anderen Worten, der Bogen ist tangential zu beiden Abschnitten.

HTML

html
<canvas id="canvas"></canvas>

JavaScript

js
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");

// Tangential lines
ctx.beginPath();
ctx.strokeStyle = "gray";
ctx.moveTo(200, 20);
ctx.lineTo(200, 130);
ctx.lineTo(50, 20);
ctx.stroke();

// Arc
ctx.beginPath();
ctx.strokeStyle = "black";
ctx.lineWidth = 5;
ctx.moveTo(200, 20);
ctx.arcTo(200, 130, 50, 20, 40);
ctx.stroke();

// Start point
ctx.beginPath();
ctx.fillStyle = "blue";
ctx.arc(200, 20, 5, 0, 2 * Math.PI);
ctx.fill();

// Control points
ctx.beginPath();
ctx.fillStyle = "red";
ctx.arc(200, 130, 5, 0, 2 * Math.PI); // Control point one
ctx.arc(50, 20, 5, 0, 2 * Math.PI); // Control point two
ctx.fill();

Ergebnis

In diesem Beispiel ist der von arcTo() erstellte Pfad dick und schwarz. Tangentenlinien sind grau, Kontrollpunkte sind rot und der Ausgangspunkt ist blau.

Erstellung einer abgerundeten Ecke

Dieses Beispiel erstellt eine abgerundete Ecke unter Verwendung von arcTo(). Dies ist einer der häufigsten Verwendungszwecke der Methode.

HTML

html
<canvas id="canvas"></canvas>

JavaScript

Der Bogen beginnt an dem von moveTo() angegebenen Punkt: (230, 20). Er wird geformt, um zu den Kontrollpunkten bei (90, 130) und (20, 20) zu passen und hat einen Radius von 50. Die Methode lineTo() verbindet den Bogen mit (20, 20) mit einer Geraden. Beachten Sie, dass der zweite Kontrollpunkt des Bogens und der von lineTo() angegebene Punkt gleich sind, was zu einer völlig glatten Ecke führt.

js
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const p0 = { x: 230, y: 20 };
const p1 = { x: 90, y: 130 };
const p2 = { x: 20, y: 20 };

const labelPoint = (p) => {
  const offset = 10;
  ctx.fillText(`(${p.x},${p.y})`, p.x + offset, p.y + offset);
};

ctx.beginPath();
ctx.lineWidth = 4;
ctx.font = "1em sans-serif";
ctx.moveTo(p0.x, p0.y);
ctx.arcTo(p1.x, p1.y, p2.x, p2.y, 50);
ctx.lineTo(p2.x, p2.y);

labelPoint(p0);
labelPoint(p1);
labelPoint(p2);

ctx.stroke();

Ergebnis

Ergebnis eines großen Radius

Wenn Sie einen relativ großen Radius verwenden, kann der Bogen an einem Ort erscheinen, an dem Sie ihn nicht erwartet haben. In diesem Beispiel verläuft die Verbindungsgerade des Bogens über der, statt unter der Koordinate, die von moveTo() angegeben wurde. Dies geschieht, weil der Radius zu groß ist, um vollständig unter den Ausgangspunkt zu passen.

HTML

html
<canvas id="canvas"></canvas>

JavaScript

js
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");

ctx.beginPath();
ctx.moveTo(180, 90);
ctx.arcTo(180, 130, 110, 130, 130);
ctx.lineTo(110, 130);
ctx.stroke();

Ergebnis

Konstruktion eines arcTo()-Pfades

Die Demo zeigt die halb-unendlichen Linien und den Kreis mit dem Zentrum C, der an den Linien bei T1 und T2 tangential ist, der verwendet wird, um den von arcTo() gerenderten Pfad zu bestimmen.

Beachten Sie, dass arcTo eine gerade Linie von P0 zu P1 erzeugen wird, wenn alle Punkte auf einer Linie liegen. Zusätzlich wird von arcTo nichts gezeichnet, wenn P0 und P1 die gleichen Koordinaten haben.

Neben der Möglichkeit, den Bogenradius mit dem Schieberegler einzustellen, können der Anfangspunkt P0 und die Kontrollpunkte P1 und P2 durch Ziehen mit der Maus bei gedrückter linker Taste bewegt werden. Die numerischen Werte können auch bearbeitet werden, und mit den Pfeiltasten können hervorgehobene Elemente im Fokus geändert werden.

Animierung der arcTo()-Zeichnung

In diesem Beispiel können Sie mit dem Bogenradius spielen, um zu sehen, wie sich der Pfad ändert. Der Pfad wird vom Startpunkt p0 mit arcTo() unter Verwendung der Kontrollpunkte p1 und p2 sowie einem variierenden Radius von 0 bis zum maximalen Radius, der mit dem Schieberegler ausgewählt wird, gezeichnet. Dann vervollständigt ein lineTo()-Aufruf den Pfad zu p2.

HTML

html
<div>
  <label for="radius">Radius: </label>
  <input name="radius" type="range" id="radius" min="0" max="100" value="50" />
  <label for="radius" id="radius-output">50</label>
</div>
<canvas id="canvas"></canvas>

JavaScript

js
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const controlOut = document.getElementById("radius-output");
const control = document.getElementById("radius");
control.oninput = () => {
  controlOut.textContent = radius = control.value;
};

const p1 = { x: 100, y: 100 };
const p2 = { x: 150, y: 50 };
const p3 = { x: 200, y: 100 };
let radius = control.value; // match with init control value

function labelPoint(p, offset, i = 0) {
  const { x, y } = offset;
  ctx.beginPath();
  ctx.arc(p.x, p.y, 2, 0, Math.PI * 2);
  ctx.fill();
  ctx.fillText(`${i}:(${p.x}, ${p.y})`, p.x + x, p.y + y);
}

function drawPoints(points) {
  points.forEach((p, i) => {
    labelPoint(p, { x: 0, y: -20 }, `p${i}`);
  });
}

// Draw arc
function drawArc([p0, p1, p2], r) {
  ctx.beginPath();
  ctx.moveTo(p0.x, p0.y);
  ctx.arcTo(p1.x, p1.y, p2.x, p2.y, r);
  ctx.lineTo(p2.x, p2.y);
  ctx.stroke();
}

function loop(t) {
  const angle = (t / 1000) % (2 * Math.PI);
  const rr = Math.abs(Math.cos(angle) * radius);

  ctx.clearRect(0, 0, canvas.width, canvas.height);

  drawArc([p1, p2, p3], rr);
  drawPoints([p1, p2, p3]);
  requestAnimationFrame(loop);
}

loop(0);

Ergebnis

Spezifikationen

Specification
HTML Standard
# dom-context-2d-arcto-dev

Browser-Kompatibilität

BCD tables only load in the browser

Siehe auch