Зачем еще одно руководство?
Потому что большинство уже существующих руководств рассматривают только основы, а все остальное приходится собирать по кусочкам поэтому я решил написать сжатое, полное руководство по canvas для программистов (а то часто пишут для простых людей которые изучают попутно и программирование).
На эту страницу с поисковиков зашли
![](http://fastgoogle.ru/microcounter/counter/9966.gif)
Canvas элемент
Canvas элемент имеет имя 'canvas' (ну кто бы мог подумать) и атрибуты 'width' и 'height', при чем стоит заметить что эти атрибуты не имеют отношения к CSS, они обозначают ширину и высоту canvas элемента в пикселях не на экране, а на координатной плоскости холста. К тому же текст внутри тега будет проигнорирован браузером с поддержкой canvas и показан в браузере без поддержки canvas.
В дальнейшем в этом учебнике мы будем использовать следующую заготовку.
<!doctype html>
<html>
<head>
<title>Тупая демка</title>
</head>
<body>
<canvas id="cnv" width="600" height="600">Ставь нормальный браузер</canvas>
<script type="text/javascript" src='your_file.js'></script>
</body>
</html>
Рисование на canvas происходит через контекст, который может быть получен вызовом метода canvas элемента getContext с аргументом '2d'.
Так что добавим в наш скрипт строку.
var ctx = document.getElementById('cnv').getContext('2d')
Прямоугольники
Прямоугольники в canvas это единственный примитив. Для работы с прямоугольниками существует всего 3 метода.
Заливаем прямоугольник
fillRect — рисует залитый прямоугольник, рассмотрим его аргументы
fillRect(float x, float y, float w, float h)
Где x и y это координаты верхнего левого угла, а w и h это ширина и высота соответственно. Давайте рассмотрим пример. Добавим в скрипт строку.
ctx.fillRect(200, 250, 200, 100)
Как многие догадались, после выполнения в центре холста будет нарисован прямоугольник шириной 200 пикселей и высотой 100 пикселей.
Обводим прямоугольник
strokeRect — работает точно также как и fillRect, но в отличие от него не заливает прямоугольник, а рисует только контуры. Добавим в скрипт строку.
ctx.strokeRect(150, 200, 300, 200)
Теперь вокруг залитого прямоугольника мы нарисовали контуры еще одного.
Отчищаем прямоугольник
clearRect — принимает те же самые аргументы, но в отличии от своих братьев не рисует, а уничтожает все что было раньше, как будто мы там ничего и не рисовали. Давайте уберем часть залитого прямоугольника,
для этого добавим в наш скрипт строку:
ctx.clearRect(350, 300, 50, 50)
Таким образом мы обрезали часть залитого прямоугольника.
Пути
В отличие от прямоугольников чтобы нарисовать или залить путь нужно выполнить несколько действия, для простоты мы рассмотрим основные методы, получив через несколько шагов готовый результат, а затем нарастим базу изученных методов. Для начала давайте отчистим наш скрипт и оставим только получение контекста.
Начинаем путь
Первым шагом к созданию пути является вызов метода beginPath, после его вызова мы добавляем под-пути (кривые, прямые) которые хранятся в специальном списке и после каждого вызова beginPath этот список обнуляется. Так что добавим в наш скрипт строчку:
ctx.beginPath()
Идем к точке
moveTo(float x, float y)
— перемещает положение курсора на (x;y).Добавим в наш скрипт строку:
ctx.moveTo(200,200)
Ведём линию к точке
lineTo(float x, float y)
— проводит линию от положения курсора к (x;y).Для примера добавим в наш скрипт строку:
ctx.lineTo(400,400)
Обводим
Завершающим моментом будет вызов метода stroke чтобы показать линию на холсте. Так что добавим строку в скрипт:
ctx.stroke()
Теперь если открыть наш пример то мы увидим, что на холсте отрисовывается линия.
Замыкаем
Если мы рисуем какую нибудь фигуру и нам нужно сделать её замкнутой то мы можем применит метод closePath. Для примера нарисуем треугольник, для этого оставим в нашем файле только получение контекста и вставим туда следующие строки:
ctx.beginPath()
ctx.moveTo(200,200)
ctx.lineTo(400,400)
ctx.lineTo(200,400)
ctx.closePath()
ctx.stroke()
Если мы откроем файл что отрисовывается треугольник. При этом мы провели только две линии, а closePath нарисовал третью чтобы замкнуть фигуру.
Заливаем
Кроме отрисовки контуров мы можем еще и залить фигуру, для этого просто заменим в нашем скрипте вызова функции stroke на вызов fill. При это если вы заливаете фигуру то не обязательно явно замыкать фигуру вызывая closePath, ведь при вызове fill фигура замкнется автоматически.
Дуги
![](https://habrastorage.org/storage/11880a79/402eeb52/d1a6c09d/3a9d17c5.png)
arc(float x, float y, float r, float startAngle, float endAngle, bool anticlockwise)
— нарисует дугу с центром в точке (x;y), радиусом — r, стартовым углом и конечным startAngle, endAngle соответственно и если anticlockwise = true то часть окружности идет против часовой стрелки, иначе по её направлению.Примечание: углы измеряются в радианах
Давайте для примера нарисуем частично залитую окружность, для этого отчистим наш скрипт, оставим только получение контекста. Затем добавим следующие строки.
ctx.beginPath()
ctx.arc(200,300,70,0,Math.PI*0.85,false)
ctx.stroke()
ctx.beginPath()
ctx.arc(200,300,70,0,Math.PI*0.85,true)
ctx.fill()
Немного другие дуги
![](https://habrastorage.org/storage/9eb87642/8faf0aa9/844bc5b7/56fa1ca2.png)
arcTo(float x1, float y1, float x2, float y2. float r)
— нарисует дугу с радиусом r заключенную между двумя отрезками — AB и BC, где точка A это положение курсора, B = (x1;y1) C = (x2;y2)Давайте для примера оставим в скрипте только получение контекста и добавим следующие строки:
ctx.beginPath()
ctx.moveTo(200,300)
ctx.arcTo(300,100,400,300,50)
ctx.stroke()
Квадратичные кривые
![](https://habrastorage.org/storage/0c988af7/7daf94dc/29971bdc/03ca2a29.png)
quadraticCurveTo(float x1, float y1, float x2, float y2)
— нарисует квадратичную кривую образованную тремя точками (положение курсора, (x1;y1), (x2;y2)). Для примера посмотрим что выполнить следующий код:
ctx.beginPath()
ctx.moveTo(100,100)
ctx.quadraticCurveTo(200,200,50,200)
ctx.stroke()
Кривые Безье
![](https://habrastorage.org/storage/73372106/51485fdf/096da14c/e27fa1ec.png)
bezierCurveTo(float x1, float y1, float x2, float y2, float x3, float y3)
— нарисует кубическу кривую Безье. Для примера добавим в наш скрипт следующий код:ctx.beginPath()
ctx.moveTo(100,100)
ctx.bezierCurveTo(200,200,100,300,50,100)
ctx.stroke()
Опять о прямоугольниках
rect(float x, float y, float w, float w)
— работает абсолютно идентично fillRect и strokeRect, но в отличие от них только добавляет прямоугольник в путь.Теперь когда мы изучили основы рисования путей, нам осталось изучить еще два важных метода при работе с путями.
Это точка на фигуре?
isPointInPath(float x, float y)
— вернет true если точка с переданными координатами находится внутри. Это метод очень хорошо использовать для проверки нажатия по какой нибудь фигуре, но для примера мы зададим все величины вручную. Добавим в наш скрипт следующие строки:ctx.beginPath()
ctx.rect(200,200,100,200)
console.log(ctx.isPointInPath(250,250))
console.log(ctx.isPointInPath(100,100))
Данный скрипт должен вывести в отладочную консоль сначала true, а затем false.
Ограничиваем область отрисовки
![](https://habrastorage.org/storage/548be0ab/1a542141/33841e83/151295c6.png)
Кроме функции stroke и fill для работы с путями существует еще и функция clip, она ничего не рисует но тем не менее выполняет важную роль, после её вызова любой объект будет рисоваться только когда он находится в области на которой определен путь, давайте рассмотрим небольшой пример:
ctx.beginPath()
ctx.arc(200,300,70,0,Math.PI*2,true)
ctx.stroke() //Нарисуем круг по которому определим область пути
ctx.clip() //Ограничим область для рисования областью путя
ctx.beginPath()
ctx.moveTo(100,320)
ctx.lineTo(500,320)
ctx.lineTo(100,250)
ctx.stroke() //Нарисуем парочку линий, при чем они будут видны только внутри круга
В ближайшем будущем (в теории по части в два дня)
Стилизация, градиенты и тени
Отрисовка картинок и текста
Трансформация и композиция
Анимация и манипуляция imageData