HTML5 Canvas

Canvas — это элемент HTML5, который позволяет рисовать графику на JavaScript. Сanvas можно использовать для текста, изображений, графики, видео, аудио, нарисовать прямоугольники, линии, градиенты и другие эффекты. Интерфейс Canvas 2D API  содержит множество функций предоставляющие возможность сделать практически всё.

Оглавление:
  1. Разница между Canvas и SVG
  2. Canvas и аппаратное ускорение
  3. Canvas 2D API
  4. Формы и цвета Canvas
  5. Нарисовать круг в canvas
  6. Кривые безье
  7. Фон в canvas
  8. Линии в canvas
  9. Текст в canvas
  10. Изображение и видео в canvas
  11. Преобразования и анимация
  12. Масштабировать элементы canvas
  13. Работа с мышью в canvas
  14. Заключение

Итак, как же вставить canvas документ HTML?

Очень просто:

<canvas id="myCanvas" style="width:300px; height:300px"></canvas>

Этот код не чего не покажет в браузере, потому что canvas пуст. Чтобы увидеть его, добавим границу.

чистый canvas
Canvas с черной границей

На веб-страницу можно добавить несколько canvas. Единственное требование чтобы каждый canvas имел свой идентификатор, иначе на странице все canvas будут одинаковые. Чтобы на странице появился canvas, нужно ссылаться на canvas в контексте. Контекст открывает доступ к 2D свойствам и методам, которые позволяют рисовать и манипулировать изображениями, видео, аудио, текстом в canvas. О контексте поговорим позже.

Каждый графический элемент имеет координаты х и у.

  • х — горизонтальные координаты
  • у — вертикальные координаты
Координаты canvas
Координаты в canvas
к меню ↑

Разница между Canvas и SVG

Важно понимать разницу между элементами Canvas и SVG. Векторная графика SVG — это файл XML. Как к SVG так как и к Canvas можно применить стили CSS и добавлять динамическое поведение с помощью SVG DOM. Canvas рисует графику и формы через JavaScript, и также принимает стили CSS и динамическое поведение.

Вот подсказки что использовать canvas или SVG.

  • Canvas быстрее при составлении сложной графики.
  • Вы можете сохранять изображение из SVG, из canvas не получится.
  • Весь canvas состоит из пикселей.

Вот преимущества SVG.

  • SVG не зависит от разрешения, он масштабируемый для разных разрешений экрана. Пример.
  • SVG — это файл XML, и предназначен для различных элементов.
  • SVG хорошо использовать при сложной анимации.

А почему не использовать один с другим?

Если графика зависит от разрешения, тогда выбераем SVG. Если вы разрабатываете игру и хотите сделать графику очень быстрой, или не хотите иметь дело с большим количеством файлов XML, тогда выбираем Canvas. В интернете они работают вместе, и дополняют друг друга.

к меню ↑

Canvas и аппаратное ускорение

В более ранних версиях браузеров, рендеринг графики как и большинство ресурсоёмких задач было возложено на CPU. Современные браузеры были переделаны в этой области, путем перевода графических ресурсоёмких задач на GPU, графический процессор для графики использует Direct2D и DirectWrite. Что ускоряет обработку графики и облегчает нагрузку на центральный процессор CPU. Пример

к меню ↑

Canvas 2D API

Объект canvas 2D API позволяет рисовать и манипулировать графикой внутри элемента canvas. Для ссылки на контекст canvas используется метод getContext.

var myCanvas = document.getElementById("myCanvas");
var context = myCanvas.getContext("2d");

В getContext для canvas 2D API есть много методов. Наиболее распространённые из них перечислены ниже.

Функции преобразования:

  • scale — позволяет масштабировать текущий контекст.
  • rotate — позволяет поворачивать х и у координаты текущего контекста.

Функции состояния:

  • save — позволяет сохранить текущее состояние контекста.
  • restore — позволяет восстановить состояние контекста из ранее сохраненного состояния.

Текстовые функции:

  • font — получает или задает шрифт для текущего контекста.
  • fillText — заполнит текст к текущему canvas.
  • MeasureText — измеряет текущую ширину указанного текста.

Это не все методы для Canvas 2D API.

к меню ↑

Формы и цвета Canvas

Прямоугольник canvas
Есть целая группа методов и функций для рисования фигур. Давайте начнем с прямоугольника. Вот соответствующие функции, доступные для рисования прямоугольников.

  • FillRect (х, у, W, H) — рисует прямоугольник в Canvas, используя текущий стиль заполнения.
  • strokeRect (х, у, W, H) — рисует окно, которое описывает данный прямоугольник в Canvas, используя текущий стиль линии.
  • clearRect (х, у, W, H) — удаляет все пиксели в Canvas, прямоугольник станет прозрачный.

Чтобы нарисовать прямоугольник, самый простой способ применить FillRect и FillStyle.

Вот как можно нарисовать черный прямоугольник:

var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
context.fillRect(5, 5, 145, 145);

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

черный прямоугольник canvas
Прямоугольник canvas

Если не указывать цвет, то цвет по умолчанию всегда будет черный. Чтобы нарисовать еще один прямоугольник, укажите для FillRect различные параметры. FillStyle может иметь любое значение цвета CSS или прозрачность. Следующий код рисует три прямоугольника canvas, разных цветов, ближний полупрозрачный.

context.fillRect(5, 5, 145, 145);
context.fillStyle = "rgb(0, 162, 232)";
context.fillRect(40, 55, 145, 145);
context.fillStyle = "rgba(255, 0, 0, 0.2)";
context.fillRect(75, 105, 145, 145);
три прямоугольника canvas
Три прямоугольника в canvas
к меню ↑

Нарисовать круг в canvas

Чтобы нарисовать круг, лучше использовании дугу. Замкнутая дуга рисует круг canvas.

  • дуга (х, у координаты и радиус startAngle, endAngle, против часовой стрелки) — дуга делает круг начиная с конца начального угла и заканчивается в конце конечного угла.

Вот как можно создать черный круг в canvas:

context.beginPath();
context.fillStyle = "rgb(0, 0, 0)";
context.arc(123, 93, 70, 0, 2 * Math.PI, true);
context.fill();
круг canvas
Черный круг в canvas

Чтобы нарисовать контур круга, используем strokeStyle вместо FillStyle. Затем вызов stroke вместо заполнения.

context.beginPath();
context.strokeStyle = "rgb(0, 0, 0)";
context.arc(123, 93, 70, 0, 2 * Math.PI, true);
context.stroke();

Контур круга не должен быть 360 градусов. Чтобы изменить форму, меняйте начальный и конечный радиус.

context.beginPath();
context.strokeStyle = "rgb(0, 0, 0)";
context.arc(123, 93, 70, 0, 0.5 * Math.PI, true);
context.stroke();
полукруг canvas
Полукруг в canvas
к меню ↑

Кривые безье

Более сложный рисунок с кривыми. Эту трудную задачу можно выполнить относительно просто с помощью функции bezierCurveTo. Эта функция указывает на текущий подкаталог с помощью контрольных точек, которые представляют собой кривую безье. Параметры с bezierCurveTo ниже.

  • bezierCurveTo (cp1x, cp1y, cp2x, cp2y, х, у) — путь точек.

Кривые должны включать в себя три пункта. Первые два пункта контроль расчетов, а третий конечная точка кривой. Вот что можно создать кривыми безье.

context.lineWidth = 20;
context.beginPath();
context.moveTo(5, 50);
context.bezierCurveTo(30, 30, 130, 530, 200, 100);
context.stroke();
Кривых Безье canvas
Рисунок с кривыми безье в canvas

С кривыми безье много чего можно нарисовать, пример смайлик в canvas.

// Лицо
context.beginPath();
context.lineWidth = 10;
context.strokeStyle = "rgb(0, 0, 0)";
context.arc(200, 233, 150, 0, 2 * Math.PI, true);
context.stroke();

// Цвет лица
context.beginPath();
context.fillStyle = "rgba(80, 100, 80, 0.4)";
context.arc(200, 233, 150, 0, 2 * Math.PI, true);
context.fill();

// Правый глаз
context.lineWidth = 20;
context.beginPath();
context.moveTo(230, 130);
context.bezierCurveTo(230, 130, 230, 130, 240, 200);
context.stroke();

// Левый глаз
context.beginPath();
context.moveTo(170, 130);
context.bezierCurveTo(170, 130, 170, 130, 160, 200);
context.stroke();

// Верхняя губа
context.beginPath();
context.moveTo(100, 230);
context.bezierCurveTo(100, 230, 200, 380, 300, 230);
context.stroke();

// Нижняя губа
context.beginPath();
context.moveTo(100, 235);
context.bezierCurveTo(105, 270, 200, 480, 300, 232);
context.stroke();

Получился смайлик.

смайлик canvas
Улыбающееся смайлик в canvas
к меню ↑

Фон в canvas

В canvas можно смешать цвета или залить фон сплошным цветом, даже сделать градиент или узор. Как и в предыдущих примерах применяется FillStyle. Эта функция заполняет фон контекста разным цветом.

Пример canvas “Цвета радуги”:

var a = 1;
for (j = 0; j < 100; j++) {
var r = 255, g = 0, b = 0;
for (i = 0; i < 150; i++) {

// Желтый
if (i < 25) g += 10.2;

// Зеленый
else if (i >= 25 && i < 50) r -= 10.2;

// Синий
else if (i >= 50 && i < 75) {
g -= 10.2;
b += 10.2;
}

// Фиолетовый
else if (i >= 75 && i < 100) r += 10.2;

// Красный
else b -= 10.2;
context.fillStyle = "rgba(" + Math.floor(r) + "," +
Math.floor(g) + "," + Math.floor(b) + "," + a + ")";
context.fillRect(3 * i, 5 * j, 3, 5); } a -= 0.01; }
градиенты canvas
Эффект цветов радуги в canvas

Еще одна особенность canvas, возможность создания градиентов.

  • addColorStop (смещение цвета) добавляет остановку цвета со значениями 0.0 смещением на одном конце градиента, 1.0 смещение на противоположном конце.
  • createLinearGradient (x0, y0, x1, y1) возвращает объект CanvasGradient, который представляет собой линейный градиент, цвет по линии определяются координатами.
  • createRadialGradient (х0, у0, г0, x1, y1, r1) возвращает объект CanvasGradient, который представляет собой радиальный градиент, цвет по конусу делают круги по указанным координатам.

Линейный градиент может быть создан вызовом createLinearGradient. Чтобы добавить цвет градиента нужно вызвать addColorStop. Вызов добавляет указанный цвет по х и у координатам. В следующем примере показан простой линейный градиент.

var gradient = context.createLinearGradient(0, 0,0, 145);
    gradient.addColorStop(0, "#00ABEB");
    gradient.addColorStop(0.5, "yellow");
    gradient.addColorStop(0.8, "green");
    gradient.addColorStop(1, "white");
    context.fillStyle = gradient;
    context.fillRect(5, 5, 145, 145);
линейные градиенты canvas
Линейный градиент в canvas
к меню ↑

Линии в canvas

Ниже свойства canvas для рисования линий, значения которые нужно заполнить, вот некоторые из них:

  • context.lineWidth = значение — возвращает ширину линии.
  • context.lineCap = значение — возвращает стиль контура линии.
  • context.lineJoin = значение — возвращает строку стилей.

Чтобы нарисовать линию вы пишите функции MoveTo и LineTo. Эти функции принимают координаты, которые говорят где именно вы хотите нарисовать линию. Ширина линии указывается в lineWidth. Чтобы появилась линия, вы должны вызвать stroke.

Следующий пример демонстрирует, как рисовать серию линий, начиная с широкой и заканчивая тонкой.

(i = 15; i > 0; i–) {
   context.strokeStyle = "blue";
   context.lineWidth = i;
   context.beginPath();
   context.moveTo(55, 15 + (15 – i) * 24);
   context.lineTo(335, 15 + (15 – i) * 24);
   context.stroke();
}
линий Canvas
Линии в сanvas

Чтобы добавить стиль к линиям или изменить контур применяется свойство lineCap. Чтобы сделать закруглённые углы, добавим для свойства LineCap значение round.

context.lineCap = "round";
Закругленные линии нарисованные Canvas
Закруглённые линии в Canvas
к меню ↑

Текст в canvas

Текст в canvas так же просто нарисовать как и линии. Функции и значения для рисования текста:

  • font = значение — возвращает настройки шрифта. Синтаксис такой же, как и в CSS.
  • textAlign = значение — возвращает параметры выравнивания текста. Возможные значения: замостить, обтекание слева, обтекание с права, и расположить по центру.
  • TextBaseline = значение — возвращает настройки выравнивания по основным направляющим.
  • fillText (текст, х, у [, MaxWidth]) — заполняет текст для указанной позиции.
  • strokeText (текст, х, у [, MaxWidth]) — штрихи текста для указанной позиции.

Метод fillText выведет текст на страницу.

context.font = '24px "Tahoma"';
context.fillText("Hello World!", 0, 0);
текст canvas
текст в canvas

Непрозрачность текста указывается значением для свойства FillStyle.

context.fillStyle = "rgba(0, 0, 0, 0.2)";
Прозрачный текст canvas
Непрозрачный текст в canvas

Эффекта тени для текста. В этом нам поможет свойство shadowOffsetX.

context.shadowOffsetX = 5;
context.shadowOffsetY = 5;
context.shadowBlur = 5;
context.shadowColor = "rgba(0, 0, 0, 1)";
Эффект тень для текста canvas
Тень для текста в canvas

Угол или цвет тени можно настроить как вам нравится.

к меню ↑

Изображение и видео в canvas

Главная функция для работы с изображениями и видео — это DrawImage.

var image = document.getElementById("mySheep");
context.drawImage(image, 10, 10, 128, 128);

<img id="mySheep" src="sheep.png" style="display:none;" />

Теперь этот код управляет рисунком.

Управление рисунком в методами и функциями canvas
Управление рисунком в canvas

Изображение теперь можно повернуть, обесцветить, добавить фильтры и не только.

Видео в canvas работает так же. Прежде всего, необходимо использовать видеотег HTML5. Уже есть много прикрепленных функций к этому элементу. HTML5 видео содержит атрибут, который определяет, будет ли браузер отображать стандартный набор контроля над видео, а также цикл, который говорит браузеру, что видео является рекурсивным. Внутри видео ничего нового, но когда вы объедините элемент видео с canvas можно придумать удивительные вещи.

Canvas и видео HTML5:

<video id="myVideo" controls loop>
   <source src="video.webm" type="video/webm">
   <source src="video.ogg" type="video/ogg">
   <source src="video.mp4" type="video/mp4">
</video>
<canvas id="myCanvas"></canvas>

Не так то много кода, правда? Можно легко расположить видео по центру canvas. Результат удивительный.

var canvas = function () {
  return {
    draw: function () {
    var video = document.getElementById("myVideo");
    var canvas = document.getElementById("myCanvas");
    var context = canvas.getContext("2d");
    var width = Math.floor(canvas.clientWidth / 100);
    var height = Math.floor(canvas.clientHeight / 100);
      canvas.width = width; canvas.height = height;
      video.play();
      context.drawImage(video, 0, 0, width, height);
  },
init: function () {
setInterval(canvas.draw, 16);
}
}
} ();

Весь фокус в том, чтобы сделать работу видео в canvas рекурсивно — это можно будет сделать только один раз. Вот почему вызывается setInterval при загрузки веб-страницы. Пример захвата кадров видео HTML5 с помощью контекста canvas.

к меню ↑

Преобразования и анимация

Вот некоторые из соответствующих свойств и функций для выполнения преобразования.

  • scale(x, y) — масштабное преобразование.
  • rotate(angle) — повернуть.
  • translate(x, y) — положение.
  • transform(m11, m12, m21, m22, dx, dy) — преобразования с аргументами.
  • setTransform(m11, m12, m21, m22, dx, dy) — новое преобразования с аргументами.

Преобразования и анимации могут работать отдельно, но если объедините их, как показано дальше, они могут сделать мощные визуальные эффекты. В следующем примере демонстрируется рисование прямоугольника каждые 250 миллисекунд и каждый прямоугольник поворачивается для получения эффекта анимации.

var can = function () {
var canvas;
var context;
return {
   draw: function () {
   var r = Math.floor(Math.random() * 255) + 70;
   var g = Math.floor(Math.random() * 255) + 70;
   var b = Math.floor(Math.random() * 255) + 70;
   var s = 'rgba(' + r + ',' + g + ',' + b + ', 0.5)';
     context.rotate(0.2 * Math.PI);
     context.fillStyle = s;
     context.fillRect(10, 0, 150, 50);
},
init: function () {
   canvas = document.getElementById("myCanvas");
   context = canvas.getContext("2d");
   context.translate(200, 250);
   setInterval(can.draw, 250);
   }
}
} ();
window.onload = can.init;

к меню ↑

Масштабировать элементы canvas

Будем придерживаться предыдущего кода за исключением вращения, каждый прямоугольник будет увеличиваться каждую секунду.

var can = function () {
var canvas;
var context;
var x = 0;
var y = 0;
function currectX() {
return x = x + 1;
}
function currectY() {
return y = y + 1;
}
return {
draw: function () {
var r = Math.floor(Math.random() * 255) + 70;
var g = Math.floor(Math.random() * 255) + 70;
var b = Math.floor(Math.random() * 255) + 70;
var s = 'rgba(' + r + ',' + g + ',' + b + ', 0.5)';
context.fillStyle = s;
context.scale(1.2,1.2);
context.fillRect(currectX(), currectY(), 5, 5);
},
init: function () {
canvas = document.getElementById("myCanvas");
context = canvas.getContext("2d");
context.translate(0, 0);
setInterval(can.draw, 1000);
}
}
} ();
window.onload = can.init;

Сложная анимация созданная группой W3C здесь. Более подробная информация о преобразованиях canvas.

к меню ↑

Работа с мышью в canvas

Вы наверно уже догадались, работать с мышью в canvas можно. Как и любой элемент веб-страницы вы можете вернуть х и у координаты мыши методами pageX и pageY.

Кода для отслеживания курсора мыши в canvas:

var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
canvas.onmousemove = function (e) {
var x = e.pageX = this.offsetLeft;
var y = e.pageY = this.offsetTop;
var div = document.getElementById("coords");
div.innerHTML = "x: " + x + " y: " + y;
};

В примере прикреплено событие захвата движения мыши, поэтому когда курсор движется, х и у координаты выводятся на веб-странице.

Холст на котором можно рисовать курсором:

var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
context.fillCircle = function (x, y, radius, fillColor) {
this.fillStyle = fillColor;
this.beginPath();
this.moveTo(x, y);
this.arc(x, y, radius, 0, Math.PI * 2, false);
this.fill();
};
context.clearTo = function (fillColor) {
context.fillStyle = fillColor;
context.fillRect(0, 0, canvas.width, canvas.height);
};
context.clearTo("#ddd");
canvas.onmousemove = function (e) {
if (!canvas.isDrawing) return;
var x = e.pageX = this.offsetLeft;
var y = e.pageY = this.offsetTop;
var div = document.getElementById("coords");
div.innerHTML = "x: " + x + " y: " + y;
var radius = 10;
var fillColor = '#ff0000';
context.fillCircle(x, y, radius, fillColor);
};
canvas.onmousedown = function (e) {
canvas.isDrawing = true;
};
canvas.onmouseup = function (e) {
canvas.isDrawing = false;
};

К JavaScript можно добавить элемент canvas и добавить пользовательские обработчики событий для обработки движения мыши.

к меню ↑

Заключение

Это не большая и не полная запись в виде руководства, знайте что эти необычные эффекты полностью работают в современных браузерах. Присылайте нам ваши эскизы, возможно они займут первое место на нашем сайте.