Рисование в JavaScript
Тэг canvas и JavaScriptЧто такое тэг canvas, т.е. "холст", и как он отображается браузерами, рассказал и показал на его собственной странице "Тэг CANVAS" Я не стал добавлять её в верхний мини-навигатор. Сделал дополнительной. Посетив предложенную страницу, думаю, станет понятно, что на ней говорить о рисовании можно весьма условно. Скорее, об оригинальном оформлении сайта. Впрочем, та страница и создавалась исключительно лишь для тестирования упомянутого тэга. Эта же страница полностью посвящена рисованию в HTML, используя JavaScript, как оно и полагается по правилам веб-технологий. Здесь показываю рисунки, созданные по этим правилам. Основы рисования в JavaScriptПримеры рисунков, сделанные с помощью тэга canvas, показываю ниже. Первыми идут самые интересные, а под ними более простые рисунки,
НО(!) именно их создание помогло мне хорошо разобраться в этом увлекательном процессе. К большинству изображениям добавил объяснения, как они были сделаны. Общий же принцип рисования в javascript вот такой. Схема рисования: прежде всего, нужно прописать открывающий и закрывающий тэги <canvas id="primer"></canvas>,
где указываем идентификатор изображения, что собираемся нарисовать. После прописывается javascript-код, который и создаёт само изображение.
<script type="text/javascript"> <— открываем тэг скрипта Кстати! Все обычные атрибуты: ширину и высоту холста, его стиль, и т.д., если они НЕ подлежат дальнейшим изменениям, можно прописывать и в коде скрипта, как показал выше, и в HTML-коде тэга canvas. Сделал так в самом первом примере. Кроме того. Важно! Показанный выше базовый код можно прописать немного иначе. Иногда встречаю примеры подобного написания в интернете. Бывает, что весь код заключают в функцию, и выглядит он уже так:
<script type="text/javascript"> <— открываем тэг скрипта Оба, показанных шаблона кода для рисования в JavaScript, работают одинаково, НО(!) последний "не терпит похожих соседей"! Он блокирует вывод ранее написанных изображений, в коде которых есть аналогичная функция загрузки документа. Такое поведение скрипта вовсе не случайно! Ведь, объект "window", который создаётся этой функцией, - коренной объект, и он превращает глобальные переменные в локальные, а они работают только внутри функций. Функции же загрузки документа - одинаковые! Вот браузер и выполняет в точности приоритетные команды скрипта, коими, дело ясное, всегда являются те, что поступили позже всех остальных. Мне же нужно было, чтобы браузер выводил абсолютно все, созданные на этой странице изображения, без исключения! Поэтому для своих рисунков использую только 1-ый вариант кода. Команды рисования скриптомДальше, чтобы было понятно, следовало бы сказать об основных командах рисования, существующих в JavaScript. К тому же! Многие из них я достаточно подробно прокомментировал как в коде страницы, так и в описаниях примеров. Рисунки в JavaScriptНу, а теперь - самое интересное! Примеры рисунков, созданные с помощью тэга canvas и его "напарника" JavaScript. Чёрно-белая шахматная доскаВ этом примере нарисовал два пустых квадрата, которые сформировали рамку вокруг изображения. * * * Цветная шахматная доскаА здесь, практически, всё то же самое. Изменил лишь цвета рамки и клеток. * * * Круг из разноцветных секторовЭтот пример рисования в JavaScript интересен тем, что круг, при каждой перезагрузке страницы, будет менять цвета своих секторов. * * * Много разноцветных кружковАналогично. Но здесь ещё интереснее! При каждой перезагрузке страницы будут меняться: форма, цвет, расположение. Короче, всё, что прописано в коде рисунка. Чтобы было понятно, где посчитал нужным, вставил в этот код комментарии. * * * Наложение рисунковСамый простой способ рисования в javascript объектов, наложенных друг на друга. * * * Наложение рисунков №2Ещё один пример наложения нескольких рисунков друг на друга. Все подробности создания этого примера подробно написал в комментариях к его коду. * * * Разные виды наложений 2-ух рисунковДва рисунка можно наложить друг на друга и по-другому. Это можно сделать с помощью функции function drawShapes(type){... ... ...}, внутри которой есть команда context.globalCompositeOperation = type;, которая, в свою очередь, может принимать одно из 11-ти значений. Накладывается круг на квадрат, т.к. круг по коду прописал позже, а значит - отображаться он будет верхним Указал все возможные значения этой команды в таблице, в ячейки которой вставил тэги <canvas id="значение"></canvas> (с идентификаторами!). Вот в них-то, как раз, благодаря присвоенным идентификаторам, JavaScript и выводит в каждой ячейке таблицы свой пример наложения двух рисунков. Кстати! Здесь можно НЕ центрировать! В HTML-коде таблицы уже есть центрирование.
* * * Разноцветные круги с обводкойВ этом примере с помощью функции JavaScript нарисовал несколько кругов разного размера и цвета. * * * Разноцветные сектораА здесь, хоть они и очень похожи на верхние (непорезанные) разноцветные круги, нарисовал совершенно другие объекты. Аналогично. Об их создании можно узнать ниже. смотреть сразу: * * * Прямоугольники с теньюНарисовал их, как и все (кроме таблицы наложений 2-ух рисунков) показанные примеры, на одном холсте. В коде есть комментарии, какой к какому относится. * * * Рисунок с линейным градиентомЧтобы нарисовать линейный градиент, сначала нужно создать сам градиент, т.е. глобальную переменную для его хранения. Его самого пока будет не видно. var gradient = context.createLinearGradient(x1, y1, x2, y2); В параметрах команды задаются координаты точек, по которым он будет проходить, т.е. из точки x1, y1 в точку x2, y2. Задаём цвета несколькими командами gradient.addColorStop(offset, "color"); В них offset - отступ задаётся со значениями от "0" до "1", а "color" - нужный цвет. Далее, созданный градиент командой context.fillStyle = gradient; мы определяем для ранее созданной переменной градиента, как стиль заливки. И, наконец, командой context.fillRect(x1, y1, x2, y2); рисуем прямоугольник для его заливки в самом начале созданным градиентом. Важно! Координаты нарисованного прямоугольника должны совпадать с координатами созданного градиента. * * * Рисунок с радиальным градиентомВ принципе, мало чем отличается от примера, показанного выше. Разница в значении глобальной переменной, предназначенной для хранения создаваемого градиента. var gradient = context.createRadialGradient(x1, y1, r1, x2, y2, r2); В параметрах команды задаётся плавный переход цвета из окружности с центром в точке x1, y1 и радиусом r1 в окружность с центром в точке x2, y2 и радиусом r2. В результате получается вот такой шар с бликом и тенью. * * * Видимость (прозрачность)Прозрачность, насыщенность рисунков в JavaScript задаётся специальной командой. context.globalAlpha = 1; В этом примере написания команды указано: полная видимость. А вообще же, значения данной команды могут находиться в диапазоне от 0 до 1, где 0 - полная прозрачность, 1 - полная видимость. Дробные значения указываются через точку Кстати! Подробно, с визуальными примерами работы разных фильтров, можно посмотреть здесь: "Прозрачность элементов" (откроется в новом окне). Правда, там рассказываю о фильтрах CSS, но каскадная таблица стилей очень похожа, и часто очень тесно связана с JavaScript. Ну, а пример работы упомянутой команды js-кода вот он. * * * Вывод изображения (растрового)А так выводятся растровые изображения, адрес которых можно прописать между тэгов <canvas id="myCanvas"><img src="logos.jpg" id="myLogo"></canvas>. Не забывать! Присвоить идентификаторы и изображению, и тэгу canvas. Далее применяем функцию window.onload = function(), в коде которой задаётся вывод нужного изображения командой (действием) ctx.drawImage(img, 10, 10); Важно! Обычным образом (без скрипта) браузер ничего не покажет, что бы мы ни писали в коде рисунка между тэгов <canvas>. Пробовал! Добавлял в тэг <img> атрибуты width и height с разными значениями. Результат всегда был один. Скрипт выводил оригинальные размеры рисунка! А за его видимость, т.е. позиционирование на холсте, отвечают два последних параметра команды ctx.drawImage(img, 10, 10); Кстати! ctx - это сокращённое context * * * ТекстВывод текста с помощью тэга canvas и переменной кода JavaScript, в которой он написан, и хранится до поры до времени. Ниже пример кода. var mText = "Это canvas и JavaScript!"; А так текст выводится скриптом на экран. * * * Дальше, прежде чем переходить к другим примерам рисования в JavaScript, показываю, как взаимодействуют 2 холста, залитых фоновым цветом. Квадрат и круг (взаимодействие 2-ух холстов)Все строчки кода данного примера подробно прокомментировал в исходнике. Чтобы немного отдалить холсты с рисунками друг от друга, использовал символ неразрывного пробела " " между ними. Это красный квадрат: Это синий круг: Интересен показанный пример тем, что в нём хорошо видно: оба холста прекрасно "уживаются" на одной строчке веб-страницы. При соответствующих их размерах, разумеется. * * * ЛинииЭтот подраздел страницы отвёл под изучение методов рисования разного вида линий. Это, пожалуй, один из самых важных навыков, который нужно освоить для того, чтобы научиться рисовать в JavaScript. Поэтому, сначала немного теории. Список команд рисованияПривёл в нём не все, а лишь некоторые, часто применяемые для рисования команды. Об остальных можно узнать далее, в подразделах с примерами их отображения. "Путь" - "Path" - определяет очертания рисунка, который может быть закрашен, то есть залит цветом, и/или обведён контурной линией (*см. список).
Подробности написания этих команд лучше всего смотреть в исходном коде примеров рисования. Работа с командами, имеющими "To", напоминает рисование карандашом БЕЗ отрыва от бумаги. А вот команда moveTo() позволяет оторвать от «бумаги» такой «карандаш», поставить его в какую-нибудь новую точку, и рисовать снова. Необходимо отметить, что позиция отрисовки, в которой заканчивается одна из команд с "To" - lineTo(), bezierCurveTo() и т. д., одновременно является и начальной позицией для следующей рисовальной команды с "To". * * * Ширина линии задаётся командой context.lineWidth, где единица соответствует одному пикселю. Значение по умолчанию - 1.0 Стиль концов линии определяет команда context.lineCap, и она может иметь три возможных значения (*см. список).
Наглядно смотреть здесь:
Пример рисования простых линийНарисовал с помощью команд JavaScript несколько линий: прямых, соединяющихся, и ниже вывел их на экран. * * * Соединение линийСтиль соединения линий задаётся командой context.lineJoin, и может принимать тоже три возможных значения (*см. список).
Наглядная памятка значений здесь: А ниже я нарисовал, и вывел их с помощью JavaScript. В код рисунка вставил комментарии, какой блок кода к какому примеру относится. * * * Ограничение длины соединенияМожно ограничить длину соединения линий с помощью команды ctx.miterLimit. Значение miterLimit – это длина, до которой может продлеваться уголок после точки стыка. Эта команда используется, только если для lineJoin выбран тип "miter" Допустимые значения команды находятся в диапазоне 1÷255px (все остальные значения будут скриптом округляться до 1 или 255). Поэтому, значения должны быть НЕ менее 1.0, поскольку любые дробные числа будут восприниматься скриптом, как 1.0, а это означает отсутствие удлинения. По умолчанию ctx.miterLimit = 10.0;. В данном примере я установил значение 25 пикселей. * * * Рисование с помощью прямых линийТеперь, изучив самые основы рисования в JavaScript, уже вполне возможно и нарисовать что-нибудь простое с помощью обычных прямых линий. Примеры ниже. Рисуем трезубецЗдесь нарисовал трезубец, очень похожий на корону. О том, как "покрасил" её в золотой цвет и обвёл её контур, подробно написал в комментариях к коду. Важно! Не забывать!
Задав, к примеру, цвет заливки с помощью команды context.fillStyle = "gold"; (золотая), нужно обязательно
запустить саму заливку командой context.fill();. Если же просто (без задания цвета заливки) прописать команду context.fill(); - зальётся чёрным (по умолчанию). * * * Рисуем домикА здесь - всего из нескольких линий у меня получился маленький домик с голубыми стенами и чёрной крышей. В его коде я всё подробно прокомментировал. Важно знать! Если прописать команду заливки "крыши" context.fill(); в самый конец кода, то рисунок весь зальётся чёрным цветом. Весь, кроме половинной толщины "стен" (обводки). * * * Конечно, рисовать только прямыми линиями можно, но уж очень примитивно. Нужно научиться эти самые линии всячески изгибать. ДугиПроще всего изогнуть прямую линию, прописав её дугой. Делается это с помощью команды context.arc(), в которой можно задать шесть значений (*см. список).
*Prim! Параметр anticlockwise сейчас установил в значение "false", т.е. рисовать по часовой стрелке, но можно было бы его и НЕ задавать. По умолчанию - это значение и так стоит в "false", т.е. рисует по часовой стрелке, а если выставить ему "true", тогда будет рисовать против часовой. Пример дуги вывел на экран, а подробности её создания в комментариях к коду. Сделал пособие (схему) для рисования различных дуг: * * * А здесь привёл вычисления, которые могут понадобиться для пересчёта из одних единиц в другие. И ещё! Полезное(!) тригонометрическое пособие (схема) для расчёта и рисования всевозможных окружностей, их секторов и дуг находится здесь: * * * Угловая линияЗакругление углов линии рисуется с помощью команды context.arcTo(), которая принимает пять обязательных параметров (*см. список).
Показанный пример создания угловой линии несколько сложнее рисования обычной дуги, т.к. линия до изгиба откуда-то приходит, и после изгиба должна продолжаться куда-то тоже. Но принципы рисования угловых линий те же самые, что и в предыдущем примере. * * * Кривые БезьеСначала немного о самих кривых. Есть две команды, для построения квадратичной (1-ая) и кубической (2-ая) кривых Безье. context.quadraticCurveTo(Px, Py, x, y); x и y - это точки, в которые нужно поставить "карандаш", а координаты Px и Py в квадратичной кривой - это дополнительные точки, используемые для её построения. В кубической кривой, соответственно, имеются ещё две дополнительные точки. Ниже нарисовал сразу два типа кривых Безье, а в коде рисунка сделал комментарии, какие строчки отвечают за какую из них. *Prim! Строчки кода можно менять местами. Результат один и тот же. * * * Цветные кривые БезьеА в этом примере рисования я раскрасил аналогичные (с такими же параметрами) кривые Безье в разные цвета, и изменил их толщину. Сделать такое НЕ сложно, однако к коду каждой кривой добавились нужные команды, и здесь, ради пробы, поменял блоки кода местами (*см. примечание предыдущего примера). * * * Ограничение области видимостиОграничить область видимости можно командой context.clip();. Важно знать! Она ничего не рисует, но после её добавления, любой объект будет виден только в том случае, если он находится внутри области, на которой определён путь. Сначала нужно нарисовать круг, и ограничить упомянутой командой область рисования этим кругом. *Prim! Если "закомментировать" эту команду, то увидим,
как на самом деле нарисованы линии. * * * Два треугольникаВ следующем примере использовал линии для отрисовки закрашенного треугольника в верхнем левом углу и контурного треугольника в нижнем правом. Установил размер холста 500 X 500 пикселей. Кстати! Для закрашенного треугольника уже не потребовалась команда ctx.closePath(), поскольку ctx.fill() - автоматически закрывает путь. Prim* Пробовал и здесь прописать закрытие. Результат такой же! * * * Думаю, хоть они и чрезвычайно важны для освоения основ рисования в JavaScript, хватит заниматься линиями. Нужно изучить и другие возможности этой технологии. * * * Круги, сектора, квадратыВ этом подразделе привожу несколько примеров объектов, нарисованных с помощью разных методов JavaScript. Частично залитые кругиИнтересны тем, что в этих примерах два рисунка сочетаются в одном. Сделаны из залитого цветом сегмента круга, и сегмента с контурной обводкой. Фактически, я использовал один и тот же код первого рисунка, лишь добавляя в него нужные команды. Рисунок №1. Частично залитый круг* * * Рисунок №2. Разная заливка круга* * * Рисунок №3. Круг из залитого сектора и цветного контура* * * Сектора круговС помощью команды arc() можно рисовать целые окружности и их сектора, а также различные дуги. context.arc(x, y, radius, startAngle, endAngle, anticlockwise); О значениях параметров этой команды подробно написал ранее. вспомнить: * * * Дальше javascript-код отрисовывает два ряда секторов кругов. В обоих рядах я начинаю с 0 радиан, и увеличиваю каждый следующий сектор на endAngle. В первом (зелёном) ряду отрисовка секторов проходит по часовой стрелке, а в нижнем (синем) — против часовой. Рисование секторов кругаНашёл в интернете тригонометрическое пособие (схему) для расчёта и рисования всевозможных окружностей, их секторов и дуг. Оно здесь: * * * Квадраты со скруглёнными угламиВ этом подразделе привожу два примера квадратов со скруглёнными углами. Сначала показываю их контура, а после - их же, но уже залитые цветом (по умолчанию чёрным). Рамку для холстов здесь сделал с помощью CSS вне тэгов canvas. Важно! ctx - это сокращённое context Можно использовать либо одно, либо другое написание в кодах, НО(!) в одном коде должно быть одинаково! Контура квадратов со скруглёнными углами №1* * * Квадраты со скруглёнными углами №2Кстати! Если в коде прописана команда заливки ctx.fill(), то команду обводки ctx.stroke() в данном случае (с чёрными квадратами) можно уже НЕ прописывать. А вот с командой закрытия ctx.closePath(); - аккуратнее! Если в данном случае её НЕ прописать, то эти чёрные квадраты станут отображаться чуть по-другому! Пробовал! А поэтому, хоть в коде рисунка и присутствует команда заливки цветом ctx.fill(), которая по правилам рисования в JavaScript должна автоматически закрывать путь, нужно всегда всё проверять! * * * Взаимодействие canvas и JavaScriptВозможности "дуэта": тэг canvas + JavaScript не ограничивается лишь рисованием. Интересно, что JavaScript позволяет не только рисовать внутри этого элемента, но и очищать его от нарисованного. Их взаимодействие можно посмотреть и проверить здесь: Использование тэга canvas и JavaScriptЭта технология работает с пикселями. Её ещё называют "динамический PNG", поэтому чаще всего этот тэг используют для создания динамических рисунков, т.е. таких, которые должны изменяться в режиме реального времени. Рисовать в HTML можно, и даже гораздо проще, используя тэг svg, когда изображение постепенно появляется в процессе написания кода. Можно легко править этот код, наблюдая, как изменяется рисунок. А вот рисовать в JavaScript таким образом не получится! Нужно прописать весь код рисунка до самого конца, чтобы он появился наконец-то на веб-странице. Где и когда? А вот где. Полезно! Отличную статью о том, когда лучше использовать тэги canvas, а что предпочтительнее делать тэгами svg, я нашёл на сайте помощи Microsoft™. Давал уже скачивать эту статью на странице "Рисование в HTML", но, думаю, она и тут будет весьма кстати! А пройти сразу в упомянутый раздел, где я, к тому же, коротко объяснил, в чём принципиальные отличия между этими двумя тэгами, здесь: По нижним навигационным стрелкам можно либо вернуться в раздел "JavaScript", к которому относится данная страница, либо посетить
"Учебные сайты", где есть много другой, разной и интересной информации. |
Все права защищены. Copyright © 2009 - Коротеев Владимир.