Координаты Canvas
На этой странице вы найдёте полезную информацию о системе координат HTML canvas, а также научитесь рисовать окружность и линию с помощью примеров кода.
HTML canvas — это мощный элемент HTML5, который позволяет создавать и манипулировать графикой на веб-странице с помощью JavaScript. Элемент <canvas> предоставляет двумерную поверхность для рисования, которую можно представить как сетку или систему координат.
На этой странице объясняется, как работает система координат canvas, как читать и задавать точки на ней, а также как перемещать, масштабировать и поворачивать эту систему с помощью трансформаций. Если вы только знакомитесь с самим элементом, сначала прочитайте введение в Canvas.
Система координат
Сетка canvas начинается в верхнем левом углу, который имеет координаты (0, 0). Отсюда:
- Ось x увеличивается вправо.
- Ось y увеличивается вниз (это противоположно тому, что большинство людей помнит из уроков математики, где y направлена вверх).
Каждая точка на canvas задаётся парой (x, y), измеренной в пикселях от этого начала координат в верхнем левом углу.
(0,0)──────── x increases → ────────►
│ ┌───────────────────────────────┐
│ │ (0,0) (300,0) │
y │ │
│ │ (150,75) │
▼ │ │
│ (0,150) (300,150)│
└───────────────────────────────┘Для canvas размером 300 × 150: (0, 0) — верхний левый угол, (300, 0) — верхний правый, (0, 150) — нижний левый, а (150, 75) — точный центр.
Контекст двумерного рендеринга
Вы никогда не рисуете непосредственно на элементе <canvas>. Вместо этого вы запрашиваете у него контекст рендеринга — объект, предоставляющий методы рисования (moveTo, lineTo, arc, fillRect и другие):
const canvas = document.getElementById("myCanvas");
const ctx = canvas.getContext("2d");getContext("2d") возвращает 2D-контекст, используемый во всех примерах ниже. (Существуют и другие типы контекста, например "webgl" для 3D, но для рисования на canvas используется "2d".) Каждая координата, передаваемая методу контекста, интерпретируется в описанной выше сетке.
Рисование линии
Для рисования прямой линии на canvas используются следующие методы:
moveTo(x,y)— задаёт начальную точку линии;lineTo(x,y)— задаёт конечную точку линии.
Чтобы нарисовать линию, используйте один из методов «отрисовки», например stroke().
Пример HTML-элемента <canvas> для рисования линии:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas width="300" height="150" style="border:1px solid #cccccc;" id="canvasExample">
Your browser does not support the HTML5 canvas tag.
</canvas>
<script>
const c = document.getElementById("canvasExample");
const ctx = c.getContext("2d");
// Starting point (0,0) is the top-left corner
ctx.moveTo(0, 0);
// Ending point (300,150) matches the canvas width and height
ctx.lineTo(300, 150);
ctx.strokeStyle = '#359900';
ctx.stroke();
</script>
</body>
</html>В приведённом выше примере линия проведена по диагонали от (0, 0) (верхний левый угол) до (300, 150) (нижний правый). Обратите внимание, что для этой одиночной линии не понадобился beginPath(): когда ещё ничего не нарисовано, moveTo/lineTo автоматически начинают новый путь. В примере с окружностью ниже используется beginPath(), поскольку это отдельная фигура — подробнее читайте в соответствующем разделе.
Другие фигуры и заливки, построенные на той же системе координат, рассматриваются в разделе Рисование на Canvas.
Рисование окружности
Для рисования окружности на canvas используются следующие методы:
beginPath()— начинает новый путь, чтобы окружность не была соединена с чем-либо, нарисованным ранее.arc(x, y, r, startAngle, endAngle)— добавляет дугу (часть окружности) к текущему пути.
Параметры arc()
| Параметр | Значение |
|---|---|
x, y | Координаты центра окружности. |
r | Радиус в пикселях. |
startAngle | Начало дуги в радианах. |
endAngle | Конец дуги в радианах. |
Углы измеряются в радианах, а не в градусах; 0 направлен вправо (положительное направление оси x), вращение происходит по часовой стрелке. Полный оборот равен 2 * Math.PI радиан (360°), поэтому полная окружность задаётся от 0 до 2 * Math.PI.
Чтобы перевести градусы в радианы, умножьте на Math.PI / 180:
const radians = degrees * (Math.PI / 180);Частичные дуги
Необязательно рисовать полную окружность. Используйте меньший конечный угол, чтобы нарисовать только её часть. Например, дуга от 0 до Math.PI (половина полного оборота) рисует нижнюю половину окружности, потому что ось y направлена вниз:
// A half-circle (bottom half) centered at (100, 75) with radius 50
ctx.beginPath();
ctx.arc(100, 75, 50, 0, Math.PI);
ctx.stroke();Пример HTML-элемента <canvas> для рисования окружности:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="exampleCanvas" width="250" height="200" style="border:1px solid #dddddd;">
The canvas tag is not supported by your browser.
</canvas>
<script>
const canvas = document.getElementById("exampleCanvas");
const ctx = canvas.getContext("2d");
ctx.beginPath();
// Center at (125, 95), radius 70. 125 is half of the 250 width.
ctx.arc(125, 95, 70, 0, 2 * Math.PI);
ctx.strokeStyle = '#1c87c9';
ctx.closePath();
ctx.stroke();
</script>
</body>
</html>В приведённом выше примере окружность центрирована в точке (125, 95) с радиусом 70.
beginPath() и closePath()
Эти два метода нередко вызывают путаницу:
beginPath()сбрасывает текущий путь и начинает новый. Вызывайте его перед каждой независимой фигурой — иначе новая фигура соединится с предыдущей, и один вызовstroke()/fill()применит стиль ко всем сразу.closePath()проводит прямую линию от текущей точки обратно к началу пути, «замыкая» контур. Для полной окружности конец уже совпадает с началом, поэтомуclosePath()здесь не имеет видимого эффекта — он включён как хорошая привычка и важен при создании незамкнутых фигур, например многоугольников.
В примере с линией ни один из методов не потребовался, так как это был единственный самостоятельный путь. Как только вы рисуете вторую фигуру, нужно использовать beginPath().
Трансформации координат
Вместо того чтобы пересчитывать каждую координату вручную, вы можете переместить, изменить масштаб или повернуть всю систему координат. Трансформации влияют на всё, что вы рисуете после их вызова.
Распространённый приём — оборачивать трансформированное рисование в save() и restore(), чтобы сетка вернулась в исходное состояние:
ctx.save(); // remember the current coordinate system
// ...transform and draw...
ctx.restore(); // put the coordinate system backtranslate(x, y)
Перемещает начало координат (0, 0) в новую позицию. После translate(50, 30) рисование в точке (0, 0) фактически будет отображаться в (50, 30):
ctx.translate(50, 30);
ctx.fillRect(0, 0, 80, 40); // top-left corner now sits at (50, 30)scale(x, y)
Умножает размер каждой координаты и измерения. scale(2, 2) делает всё вдвое больше; scale(1, 0.5) сохраняет ширину, но вдвое уменьшает высоту:
ctx.scale(2, 2);
ctx.fillRect(10, 10, 30, 30); // drawn at (20, 20), 60×60 in real pixelsrotate(angle)
Вращает систему координат по часовой стрелке вокруг текущего начала. Угол задаётся в радианах, как и в arc(). Поскольку вращение происходит вокруг (0, 0), обычно сначала применяют translate() к нужной точке поворота:
ctx.translate(100, 75); // move origin to the pivot point
ctx.rotate(45 * Math.PI / 180); // rotate 45° clockwise
ctx.fillRect(-25, -25, 50, 50); // a square centered on the pivotТрансформации позволяют работать с той же сеткой координат — они просто перемещают или изменяют форму этой сетки. О рисовании текста в этой системе читайте в разделе Canvas: текст.