Spec-Zone.ru › Web APIs

CanvasRenderingContext2D: метод arcTo()

Базовая линия Широко доступна

Эта функция хорошо зарекомендовала себя и работает на многих устройствах и версиях браузеров. Она доступна во всех браузерах с июля 2015 года.

  • Узнать больше
  • Полная совместимость
  • Отправить отзыв

Метод CanvasRenderingContext2D.arcTo() API Canvas 2D добавляет дугу окружности к текущей подтраектории, используя заданные точки управления и радиус. Дуга автоматически подключается к последней точке траектории прямой линией, если это необходимо, например, если начальная точка и точки управления находятся на одной прямой.

Этот метод обычно используется для создания закруглённых углов.

Примечание: При использовании относительно большого радиуса вы можете получить неожиданные результаты: соединительная линия дуги будет направлена в нужном направлении, чтобы соответствовать заданному радиусу.

Синтаксис

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

Параметры

x1

Координата x первой точки управления.

y1

Координата y первой точки управления.

x2

Координата x второй точки управления.

y2

Координата y второй точки управления.

radius

Радиус дуги. Должен быть неотрицательным.

Примечания по использованию

Предположим, что P0 — это точка на траектории, когда вызывается arcTo(), P1 = (x1, y1) и P2 = (x2, y2) — это первая и вторая точки управления соответственно, а r — это radius заданный в вызове:

  • Если r отрицательно, возникает IndexSizeError исключение.
  • Если r равно 0, arcTo() ведёт себя так, как если бы P0, P1 и P2 были коллинеарны (на одной прямой).
  • В случае, когда все точки коллинеарны, рисуется линия от P0 до P1, если только точки P0 и P1 не совпадают, в этом случае ничего не рисуется.

Эти условия могут быть созданы в примере Создание траектории с помощью arcTo() ниже, чтобы увидеть результаты.

Возвращаемое значение

None (undefined).

Исключения

IndexSizeError DOMException

Выбрасывается, если radius имеет отрицательное значение.

Примеры

Как работает arcTo()

Один из способов понять arcTo() — представить две прямые: одну от начальной точки до первой точки управления, а другую — от этой точки до второй точки управления. Без arcTo(), эти две отрезки образовали бы острый угол: arcTo() создаёт дугу окружности в этом углу и сглаживает его. Другими словами, дуга касается обеих отрезков.

HTML

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

JavaScript

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();

Результат

В этом примере траектория, созданная с помощью arcTo() — толстая и чёрная. Касательные линии серые, точки управления красные, а начальная точка — синяя.

Создание закруглённого угла

В этом примере создается угол с закругленными углами с помощью arcTo(). Это одно из наиболее распространённых применений метода.

HTML

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

JavaScript

Дуга начинается в точке, указанной moveTo(): (230, 20). Она формируется, чтобы соответствовать контрольным точкам в (90, 130) и (20, 20), и имеет радиус 50. Метод lineTo() соединяет дугу с (20, 20) прямой линией. Обратите внимание, что вторая контрольная точка дуги и точка, указанная lineTo(), совпадают, что создаёт полностью плавный угол.

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();

Результат

Результат с большим радиусом

Если вы используете относительно большой радиус, дуга может появиться в неожиданном месте. В этом примере соединяющая линия дуги проходит над, а не под, координатой, указанной moveTo(). Это происходит потому, что радиус слишком велик для того, чтобы дуга полностью поместилась под начальной точкой.

HTML

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

JavaScript

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();

Результат

Создание пути arcTo()

Демонстрация показывает полубесконечные линии и окружность с центром C, касающиеся линий в T1 и T2, используемых для определения пути, отрисованного с помощью arcTo().

Обратите внимание, что arcTo создаст прямую линию от P0 до P1, когда все точки находятся на одной линии. Кроме того, ничего не рисуется arcTo если P0 и P1 имеют одинаковые координаты.

Помимо возможности задать радиус дуги с помощью ползунка, начальную точку P0 и контрольные точки P1 и P2 можно переместить, удерживая нажатой левую кнопку мыши. Также можно редактировать числовые значения, а стрелки на клавиатуре можно использовать для изменения подчёркнутого элемента, который находится в фокусе.

Анимация отрисовки arcTo()

В этом примере вы можете поэкспериментировать с радиусом дуги, чтобы увидеть, как изменяется путь. Путь рисуется от начальной точки p0 с помощью arcTo() с контрольными точками p1 и p2 и радиусом, изменяющимся от 0 до максимального радиуса, выбранного ползунком. Затем вызов lineTo() завершает путь до p2.

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

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);

Результат

Спецификации

Спецификация
HTML
# dom-context-2d-arcto-dev

Совместимость с браузерами

Рабочие столы Мобильные устройства
Chrome Edge Firefox Opera Safari Chrome Android Firefox for Android Opera Android Safari на iOS Samsung Internet WebView Android
arcTo 1 12 1.5 11.6 2 18 4 12 1 1.0 4.4

См. также

  • Интерфейс, определяющий этот метод: CanvasRenderingContext2D

© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/arcTo

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API