Текст на Canvas
HTML5 canvas позволяет рисовать текст с помощью свойств шрифта. Примеры fillText, strokeText, добавления цвета и центрирования текста.
Элемент HTML5 <canvas> позволяет рисовать текст непосредственно на растровой поверхности. В отличие от обычного текста DOM, текст на canvas отрисовывается как пиксели — после нанесения у него нет разметки, его нельзя выделить, скопировать или прочитать с помощью экранных считывателей, и он никогда не перестраивает поток. Его внешний вид управляется через контекст рисования (getContext("2d")), а не через CSS, что делает текст на canvas идеальным для графики, диаграмм, игрового интерфейса и генерации изображений, но плохим выбором для основного текста страницы.
Эта глава опирается на введение в Canvas и основы рисования. Об окраске текста градиентами см. Градиенты Canvas.
Свойства и методы
| Свойство / Метод | Описание |
|---|---|
| font | Возвращает текущие настройки шрифта и позволяет их изменить. |
| textAlign | Возвращает текущие настройки выравнивания текста и позволяет их изменить. Свойство принимает следующие значения: start, end, left, right и center. Обратите внимание, что start и end зависят от направления текста. |
| textBaseline | Возвращает текущие настройки выравнивания по базовой линии и позволяет их изменить. Свойство принимает следующие значения: top, hanging, middle, alphabetic, ideographic и bottom. |
| fillStyle | Задаёт цвет, используемый для заливки текста. |
| strokeStyle | Задаёт цвет, используемый для обводки текста. |
| fillText(text, x, y [, maxWidth]) | Рисует закрашенный текст в позиции, указанной координатами x и y. Необязательный аргумент maxWidth уменьшает текст так, чтобы он никогда не превышал заданную ширину в пикселях. |
| strokeText(text, x, y [, maxWidth]) | Обводит (рисует контур) текст в позиции, указанной координатами x и y. Также принимает необязательный аргумент maxWidth. |
| measureText(text) | Возвращает объект TextMetrics, свойство width которого указывает ширину текста при текущем значении font. Полезно для центрирования, переноса строк или подгонки текста по ширине. |
Свойство font
Свойство font принимает то же значение, что и сокращённое CSS-свойство font. Можно объединить стиль, начертание, размер и гарнитуру в одну строку, например "italic bold 18px serif". Если задать только размер и гарнитуру (например, "30px Arial"), остальные параметры примут значения по умолчанию. Всегда указывайте размер и гарнитуру — если пропустить любой из них, объявление окажется недействительным и изменение будет проигнорировано.
ctx.font = "italic bold 18px serif";
ctx.font = "small-caps 24px 'Courier New', monospace";
ctx.font = "30px Arial"; // size + family only — also validПример метода fillText():
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="exampleCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
Your browser does not support the canvas element.
</canvas>
<script>
const canvas = document.getElementById("exampleCanvas");
const ctx = canvas.getContext("2d");
ctx.font = "30px Arial";
ctx.fillText("Hello World", 70, 80);
</script>
</body>
</html>Пример метода strokeText():
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="exampleCanvas" width="250" height="150" style="border:1px solid #d3d3d3;">
Your browser does not support the canvas element.
</canvas>
<script>
const canvas = document.getElementById("exampleCanvas");
const ctx = canvas.getContext("2d");
ctx.font = "27px Arial";
ctx.strokeText("Canvas text", 40, 70);
</script>
</body>
</html>Пример добавления цвета и центрирования текста:
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="exampleCanvas" width="400" height="250" style="border:1px solid #d3d3d3;">
Your browser does not support the canvas element.
</canvas>
<script>
const canvas = document.getElementById("exampleCanvas");
const ctx = canvas.getContext("2d");
ctx.font = "40px Comic Sans MS";
ctx.fillStyle = "red";
ctx.textAlign = "center";
ctx.fillText("Canvas Text", canvas.width / 2, canvas.height / 2);
</script>
</body>
</html>Выравнивание текста с помощью textAlign
Координата x, передаваемая в fillText/strokeText, является точкой привязки. Свойство textAlign определяет, где текст располагается относительно этой точки. Значение по умолчанию — "start", которое следует направлению текста: для текста слева направо оно работает как "left", для текста справа налево — как "right". При "left" точка привязки находится у левого края; при "center" текст центрируется по точке привязки; при "right" точка привязки — у правого края; "start" и "end" привязываются к краям в соответствии с направлением текста.
Пример ниже рисует вертикальную опорную линию в x = 150, затем выводит три метки, привязанные к той же x с разными значениями textAlign, чтобы наглядно показать, как каждое из них позиционирует текст.
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="exampleCanvas" width="300" height="160" style="border:1px solid #d3d3d3;">
Your browser does not support the canvas element.
</canvas>
<script>
const canvas = document.getElementById("exampleCanvas");
const ctx = canvas.getContext("2d");
const x = 150;
// Reference line at the anchor x
ctx.strokeStyle = "#d3d3d3";
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, 160);
ctx.stroke();
ctx.font = "20px Arial";
ctx.fillStyle = "black";
ctx.textAlign = "left";
ctx.fillText("left", x, 40);
ctx.textAlign = "center";
ctx.fillText("center", x, 80);
ctx.textAlign = "right";
ctx.fillText("right", x, 120);
</script>
</body>
</html>Вертикальное позиционирование текста с помощью textBaseline
Координата y отсчитывается от базовой линии текста, а textBaseline определяет, какая часть глифов с ней совпадает. По умолчанию используется "alphabetic", при котором y находится примерно у нижнего края строчных букв вроде «x». Установите "top", чтобы y соответствовала верхнему краю текста, или "middle", чтобы вертикально центрировать текст по y — удобно, когда нужно разместить текст по центру блока.
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="exampleCanvas" width="320" height="120" style="border:1px solid #d3d3d3;">
Your browser does not support the canvas element.
</canvas>
<script>
const canvas = document.getElementById("exampleCanvas");
const ctx = canvas.getContext("2d");
const y = 60;
// Reference line at the anchor y
ctx.strokeStyle = "#d3d3d3";
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(320, y);
ctx.stroke();
ctx.font = "20px Arial";
ctx.fillStyle = "black";
ctx.textBaseline = "top";
ctx.fillText("top", 10, y);
ctx.textBaseline = "middle";
ctx.fillText("middle", 90, y);
ctx.textBaseline = "bottom";
ctx.fillText("bottom", 200, y);
</script>
</body>
</html>Текст с заливкой и обводкой (strokeText + fillText)
Можно совместить заливку и обводку одного текста, чтобы получить эффект контурных букв. Сначала вызовите fillText, чтобы нанести сплошной цвет, затем поверх него — strokeText, чтобы контур оставался чётким. Используйте fillStyle, strokeStyle и lineWidth для управления внешним видом.
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="exampleCanvas" width="360" height="120" style="border:1px solid #d3d3d3;">
Your browser does not support the canvas element.
</canvas>
<script>
const canvas = document.getElementById("exampleCanvas");
const ctx = canvas.getContext("2d");
ctx.font = "bold 60px Arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
const x = canvas.width / 2;
const y = canvas.height / 2;
ctx.fillStyle = "gold";
ctx.fillText("Canvas", x, y);
ctx.lineWidth = 2;
ctx.strokeStyle = "black";
ctx.strokeText("Canvas", x, y);
</script>
</body>
</html>Измерение текста с помощью measureText()
measureText() возвращает объект TextMetrics, описывающий, как текст будет отрисован при текущем значении font. Свойство width используется чаще всего: его можно вычесть из ширины canvas для ручного центрирования текста или сравнить с доступной шириной, чтобы разбить длинный текст на несколько строк.
<!DOCTYPE html>
<html>
<head>
<title>Title of the document</title>
</head>
<body>
<canvas id="exampleCanvas" width="320" height="100" style="border:1px solid #d3d3d3;">
Your browser does not support the canvas element.
</canvas>
<script>
const canvas = document.getElementById("exampleCanvas");
const ctx = canvas.getContext("2d");
const text = "Measured!";
ctx.font = "30px Arial";
const metrics = ctx.measureText(text);
// Center horizontally without changing textAlign
const x = (canvas.width - metrics.width) / 2;
ctx.fillText(text, x, 55);
</script>
</body>
</html>Совет: если нужно лишь вписать текст в фиксированную ширину, более простой вариант — необязательный аргумент
maxWidth:ctx.fillText("Long label", 10, 40, 120)уменьшает текст так, чтобы он не превышал 120 пикселей.