Pull to refresh

Еще одно Canvas руководство [1]: Canvas элемент, прямоугольники, пути

Reading time5 min
Views19K

Зачем еще одно руководство?


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

На эту страницу с поисковиков зашли

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 фигура замкнется автоматически.

Дуги



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()

Немного другие дуги



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()


Квадратичные кривые



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()


Кривые Безье



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.

Ограничиваем область отрисовки



Кроме функции 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
Tags:
Hubs:
Total votes 84: ↑76 and ↓8+68
Comments29

Articles