Canvas API

Drawing shapes

const ctx = canvas.getContext("2d", { alpha: false, }); - создание 2d контекста с настройками

Drawing rectangles

ctx.fillRect(x, y, width, height) - рисует закрашенный прямоугольник.

ctx.strokeRect(x, y, width, height) - рисует прямоугольник.

ctx.clearRect(x, y, width, height) - заменяет выбранную область цветом по умолчанию (прозначным либо черным).

Paths

Path - список точек, соединенных линиями, которые могут иметь разные формы.

Создание path

ctx.beginPath() - создает новый path. Будущие команды по отрисовке будут относиться к этому path.

Методы для отрисовки path

ctx.moveTo(x, y) - переносит карандаш (кисть) в заданную точку.

ctx.lineTo(x, y) - проводит прямую линию из текущей точки к заданной.

ctx.arc(x, y, radius, startAngle, endAngle, counterclockwise) - рисует дугу окружности с центром в заданной точке. Углы задаются в радианах (Math.PI - это 180 градусов).

ctx.arcTo(x1, y1, x2, y2, radius) - рисует дугу окружности с заданным радиусом по двум опорным точкам.

ctx.closePath() - чертит прямую линию из текущей точки в начальную координату текущего path.

ctx.rect(x, y, width, height) - вызывает ctx.moveTo(x, y) и добавляет к текущему пути прямоугольник.

Отображение path на холсте

ctx.stroke() - обводит текущий path линией с заданными stroke стилями.

ctx.fill(fillRule) - вызывает ctx.closePath() и закрашивает содержимое контура path.

  • fillRule = ['nonzero'] | 'evenodd' - правило заполнение контура

Applying styles

Line styles

ctx.strokeStyle - задает цвет color контура фигуры при выполнении ctx.stroke().

ctx.fillStyle - задает цвет color окрашивания фигуры при выполнении ctx.fill().

  • color - строковое представление CSS-цвета. Цвет по умолчанию - черный. Можно установить цвет с альфа-каналом, например 'rgb(100 100 100 / 0.7)'. Прозрачность также можно задать свойством ctx.globalAlpha

ctx.lineCap - задает тип type концов линии.

  • type = ['butt'] | 'round' | 'square'

ctx.lineJoin - задает тип value соединения линий.

  • value = ['miter'] | 'bevel' | 'round'

ctx.setLineDash(sequence) - задает стиль для пунктирной линии.

  • sequence - массив, задающий длину линий и расстояние между в px, например, [3, 10, 7, 10]

ctx.lineDashOffset - задает смещение пунктирной линии.

Shadows

ctx.shadowOffsetX - задает смещение тени по горизонтали, по умолчанию 0.

ctx.shadowOffsetY - задает смещение тени по вертикали, по умолчанию 0.

ctx.shadowBlur - задает величину размытия тени, по умолчанию 0.

ctx.shadowColor - задает цвет тени, по умолчанию прозрачный.

Drawing text

ctx.fillText(text, x, y [, maxWidth]) - отрисовывает текст по указанным координатам.

ctx.strokeText(text, x, y [, maxWidth]) - отрисовывает контур текста по указанным координатам.

ctx.font - задает стиль отрисованного текста, по умолчанию '10px sans-serif'.

ctx.textAlign - задает выравнивание align текста по горизонтали относительно координаты x.

  • align = ['start'] | 'end' | 'left' | 'right' | 'center'

ctx.textBaseline - задает выравнивание align текста по вертикали относительно координаты y.

  • align = 'top' | 'hanging' | 'middle' | ['alphabetic'] | 'ideographic' | 'bottom'

Text measurements

ctx.measureText(text) - возвращает объект, содержащий ширину текста и другие параметры до его отрисовки.

const text = ctx.measureText("hello canvas"); console.log(text.width); // 55.5908203125

Using images

Создание изображения

const img = new Image(); img.src = "myImage.png"; img.onload = () => { ... }; // после загрузки изображения, можно приступать к его отрисовке

Отрисовка изображения

Для отрисовки используется метод drawImage, который может вызываться в 3 разных вариантах:

ctx.drawImage(image, x, y) - отрисовывает изображение по заданным координатам.

ctx.drawImage(image, x, y, width, height) - отрисовывает изображение с заданной шириной и высотой.

ctx.drawImage(image, sx, sy, sWidth, sHeight, x, y, width, height) - отрисовывает часть изображения.

  • image - изображение
  • x, y - координаты для отрисовки
  • width, height - ширина и высота отрисовываемого изображения
  • sx, sy - координаты части исходного изображения
  • sWidth, sHeight - ширина и высота части исходного изображения

Transformations

Сохранение и восстановление состояния

Состояния canvas хранятся в стеке. Каждый раз при вызове ctx.save() текущее состояние добавляется в стек (аналог метода push). А при вызове ctx.restore() - достается из стека (аналог метода pop). Состояние включает в себя текущие трансформации, stokeStyle, fillStyle, lineWidth и другие атрибуты.

ctx.save() - сохраняет состояние в стек.

ctx.restore() - восставнавливает последнее состояние в стеке и удаляет его из стека.

Смещение

ctx.translate(x, y) - перемещает начало координат canvas на заданную величину. Перед вызовом рекомендуется сохранить состояние, а после выполнения всех операций его восстановить.

Вращение

ctx.rotate(rad) - вращает координатную сетку canvas по часовой стрелке на заданное число радиан относительно начала координат.

Чтобы повернуть прямоугольник относительно центра, сначала необходимо выполнить ctx.translate(xCenter, yCenter), затем ctx.rotate(Math.PI / 180 * angle), затем вернуть начало координат через ctx.translate(-xCenter, -yCenter) и отрисовать прямоугольник через ctx.drawRect.

Масштабирование

ctx.scale(x, y) - увеличивает canvas в x раз по горизонтали и в y раз по вертикали.

Используя отрицательные x, y можно выполнить зеркальное отражение оси.

Матрица трансформации

ctx.transform(a, b, c, d, e, f) - позволяет задать сразу несколько трансформаций, в том числе искажение skewing. Значения по умолчанию: (1, 0, 0, 1, 0, 0).

  • a - горизонтальное масштабирование
  • b - горизонтальное искажение (skewing)
  • c - вертикальное искажение (skewing)
  • d - вертикальное масштабирование
  • e - горизонтальное смещение
  • f - вертикальное смещение

Compositing and clipping

globalCompositeOperation

Свойство устанавливает то, как новое изображение будет нарисовано поверх существующего содержимого.

ctx.globalCompositeOperation - задает тип операции, который будет использован в режиме наложения. Имеет любое из следующих значений:

  • 'source-over' - значение по умолчанию, при котором новые фигуры отображаются поверх существующего содержимого холста
  • 'source-in' - новая фигура отображается только в том месте, где и она, и целевой холст накладываются друг на друга, все остальное становится прозрачным
  • 'source-out' - новая фигура рисуется там, где она не перекрывает существующее содержимое холста
  • 'source-atop' - новая фигура рисуется только там, где она перекрывает существующее содержимое холста
  • 'destination-over' - новые фигуры рисуются позади существующего содержимого холста
  • 'destination-in' - существующее содержимое холста сохраняется там, где новая фигура и существующее содержимое холста пересекаются. Все остальное становится прозрачным
  • 'destination-out' - существующий контент сохраняется там, где он не перекрывает новую форму
  • 'destination-atop' - существующее содержимое холста сохраняется только там, где оно перекрывает новую фигуру. Новая фигура отображается позади содержимого холста
  • 'lighter' - цвет определяется путем сложения цветов там, где обе фигуры пересекаются
  • 'copy' - показывать только новую фигуру
  • 'xor' - фигуры становятся прозрачными там, где они накладываются друг на друга
  • 'multiply' - пиксели верхнего слоя умножаются на соответствующий пиксель нижнего слоя. В результате изображение получается более темным
  • 'screen' - пиксели инвертируются, перемножаются и снова инвертируются. В результате получается более светлое изображение (похож на lighter)
  • 'overlay' - комбинация значений multiply и screen. Темные участки становятся темнее, а светлые - светлее
  • 'darken' - сохраняет самые темные пиксели обоих слоев (похож на multiply)
  • 'lighten' - сохраняет самые светлые пиксели обоих слоев (похож на lighter)
  • 'color-dodge' - разделяет нижний слой на перевернутый верхний слой
  • 'color-burn' - делит перевернутый нижний слой на верхний, а затем инвертирует результат
  • 'hard-light' - комбинация значений multiply и screen как в значении overlay, но с перестановкой верхнего и нижнего слоев
  • 'soft-light' - более мягкая версия значения hard-light. Чистый черный или белый цвет не приводит к получению абсолютно черного или белого цвета
  • 'difference' - вычитает нижний слой из верхнего или наоборот, чтобы всегда получать положительное значение
  • 'exclusion' - как значение difference, но с меньшим контрастом
  • 'hue' - сохраняет яркость и насыщенность цвета нижнего слоя, при этом беря оттенок верхнего слоя. luma, saturation - не меняются, hue - меняется
  • 'saturation' - сохраняет яркость и оттенок цвета нижнего слоя, при этом беря насыщенность верхнего слоя. luma, hue - не меняются, saturation - меняется
  • 'luminosity' - сохраняет оттенок и насыщенность цвета нижнего слоя, при этом беря яркость верхнего слоя. hue, saturation - не меняются, luma - меняется
  • 'color' - сохраняет яркость цвета нижнего слоя, при этом беря насыщенность верхнего слоя. luma - не меняется, saturation - меняется

Clipping

ctx.clip() - превращает текущий path в маску, используется вместо ctx.closePath().

Маска хранится в состоянии canvas.

Для инвертирования маски (отрисовки содержимого снаружи) нет специального свойства. Однако можно сделать маской фигуру с отверстием внутри.

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

Прямоугольник, нарисованный через ctx.rect() предполагает направление по часовой стрелке.

Пример такой маски:

ctx.beginPath(); ctx.rect(-75, -75, 150, 150); // Outer rectangle ctx.arc(0, 0, 60, 0, Math.PI * 2, true); // Hole anticlockwise ctx.clip();

Basic animations

Последовательность шагов:

  1. Если фигуры не будут занимать все пространство, очистить холст через ctx.clearRect().
  2. Сохранить текущий state (если будут применяться новые стили, трансформации и тд).
  3. Отрисовать анимированные фигуры.
  4. Восстановить сохраненный state.

Pixel manipulation

ImageData - объект, который позволяет напрямую работать с пикселями. Имеет следующие read-only свойства:

  • width - количество пикселей в ширину
  • height - количество пикселей в высоту
  • data - одноразмерный массив Uint8ClampedArray, в котором каждые 4 элемента со значениями от 0 до 255 содержат информацию об одном пикселе (RGBA). Порядок пикселей - слева направо, затем сверху вниз. Массив содержит height * width * 4 байтов данных (и столько же элементов)

Создание пустого массива

const myImageData = ctx.createImageData(width, height) - создание объекта ImageData с указанными размерами. Всем пикселям предварительно задан прозрачный черный цвет rgb(0 0 0 / 0%), то есть массив хранит одни нули.

const myImageData = ctx.createImageData(anotherImageData) - создание объекта ImageData с размерами anotherImageData и пикселями прозрачного черного цвета.

Получение пиксельных данных из контекста

const myImageData = ctx.getImageData(x, y, width, height) - возвращает объект ImageData с пиксельными данными заданной области холста.

Отрисовка пиксельных данных в контексте

ctx.putImageData(myImageData, x, y) - отрисовывает пиксели из myImageData начиная с координат x и y.

Сохранение изображений

Метод toDataURL() объекта canvas возвращает представление изображения в виде строки data URL.

canvas.toDataURL('image/png') - значение по умолчанию.

canvas.toDataURL('image/jpeg', quality) - JPG формат, позволяет задать необязательный параметр quality со значением от 0 до 1, где 0 - изображение в плохом качестве, но небольшое по размеру.

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

const link = document.createElement("a"); link.href = canvas.toDataURL("image/png"); link.download = "canvas_image.png"; // Имя файла document.body.append(link); link.click(); link.remove();