Скажу сразу, я хочу объяснить логику работы с canvas'ом. Код очень простой, я надеюсь, это подтолкнет вас к изучению такого инструментария как canvas. А так же это очень хорошая практика для начинающего JS программиста.
Перейдем к коду. Напишем простую генерацию квадратов разного цвета на полотне. Код вы можете увидеть сразу весь, далее я объясню его.
Что нам нужно сделать?
- Получить canvas и его 2D контекст (Если вы раньше не делали подобного, то не переживайте, это делает 2-мя строчками кода)
- Сделаем наш канвас немного адаптивным
- Зададим нужные нам переменные и свойства
- Отрисовка элемента на canvas'e
- При ресайзе меняем размер канваса
Работу в canvas можно разделить на 3 этапа.
- Настройка нужных нам свойств (толщина пера, цвет заливки, цвет линии и прочие свойства)
- Рисуем элемент
- Если мы делаем что-то динамическое. Например, игру, анимацию, систему частиц и прочие элементы, то создаем цикл и в него закидываем рендер (отрисовку) наших объектов
Ну хорошо, вернемся к нашему коду.
1. Как я и говорил, две строчки кода и мы можем манипулировать полотном
Получить элемент по Id это стандартный API браузера, а вот getContext это метод самого canvas'a. Можно получить и 3D контекст, но в данный момент он нам не нужен.
2. Второй пункт, третий и пятый я объединю т.к. идет объявление переменных + код здесь одинаковый. Можно даже сделать отдельную функцию т.к. уже идет дублирование кода, а это плохо.
Переменные width и height нам потребуются дальше.Также не забудьте вызвать функцию ReSize после получения контекста canvas'а.
Нам потребуется еще объект options. В нем мы будем хранить все настройки.
opacity — скорость с которой наши элементы будут затираться на canvas'e
count — количество кубов, которые мы будем создавать за один прогон функции
fps — думаю объяснять не нужно для чего… правда работает странно…
color — здесь лежит маска, которая представляет нашу цветовую палитру
hue — это цветовой тон в диапазоне от 0 до 360. На картинку будет понятней
divisionSpeed — это переменная с помощью которой мы сможем регулировать скорость смены цвета
4. Нам остается лишь создать цикл, функцию для отрисовки и вызвать всё это.
Создаем функцию Init, она нужна для инициализации цикла. У window есть отличный метод requestAniimationFrame() который позволяет зациклить вызов нужной нам функции. Так же внутри Init мы вызываем функцию Step() в которой и хранится код отрисовки наших кубиков.
Отрисовку мы будем делать в цикле, чтобы отрисовывать сразу 100 элементов. Внутри цикла, первым же делом мы ставим условие, которое позволяет нам выбрать цветовой тон в диапазоне от 0 до 360, тем самым цвета наших кубиков будут меняться. Две последующие строчки можно объединить в одну, тем самым напрямую задать цвет заливки фигуры. ctx.fillStyle позволяет задать цвет заливки, а ctx.fillRect(точка x, точка y, ширина, высота) позволяет нарисовать фигуру. Задаем рандомную высоту с шириной, но в диапазоне наших размеров.
Две строчки после цикла, это для очистки экрана. Вы уже знаете, что fillstyle позволяет задать цвет заливки, мы задаем белый цвет с прозрачностью равной opacity из объекта options. А так же запускаем отрисовку очищающей фигуры из точки 0:0 с размерами равными размерам нашего canvas'a.
Нам остается только вызвать функцию Init в любом месте нашей программы.
Если вы все еще сомневаетесь, что можно делать красивые вещи с помощью canvas, то вот вам один из примеров.
Если вас заинтересовал canvas, то самое время продолжить изучение этой технологии. Я не могу вам посоветовать хорошую статью по изучению т.к. для меня было очень скучно читать про canvas и для себя я ничего хорошего не сохранил в закладки. А на youtube очень мало хороших видео по canvas'у, а те что и можно посмотреть содержат лишь 10% нужной инфы и 30% воды, а всё остальное время пишут код с ошибками и проектируют его на ходу. На мой взгляд, самое лучшее это взять какой-то простой пример и попытаться самому его реализовать.
Комментарии (20)
Zenitchik
11.01.2019 22:57Переменные width и height нам потребуются дальше.
В глобальном пространстве имён? Вы серьёзно?
Также не забудьте вызвать функцию ReSize после получения контекста canvas'а.
Зачем? Она же не работает с контекстом.EpicLegend_gg Автор
12.01.2019 10:55Я не пишу библиотеку, которой потом «возможно» будут пользоваться. Это простой пример. Лучше допускать ошибки, чем не писать вовсе код.
ReSize нужно один раз вызвать перед основным циклом т.к. он установит нужные размеры канвасу и обновит значения переменных width и heightZenitchik
12.01.2019 14:43+1Это простой пример.
Сразу содержащий плохой пример…
Лучше допускать ошибки, чем не писать вовсе код.
Как PET-проект — может быть, но не как совет другим.
ReSize нужно один раз вызвать перед основным циклом
Именно, и это не обязательно
после получения контекста canvas'а.
Я лично рекомендую его запускать сразу после загрузки страницы.Keyten
12.01.2019 15:45Да не так уж и плохо, например в jsfiddle в маленьких демках тоже вполне допустимо юзать глобальные переменные типа width / height.
tamerlan676
12.01.2019 10:52На сервисе udacity есть курс по Canvas. Вполне себе достойный.
muhaa
12.01.2019 13:05+7Если вас заинтересовал canvas, то самое время продолжить изучение этой технологии.
1. Функции для рисования графики были и есть в любой мало-мальски развитой среде разработки, начиная с бейсика или Турбо-паскаля в 80-ых.
2. Эти функции для рисования во всех средах реализуются почти одинаковым и очевидным образом, Canvas — не исключение.
3. Для освоения функций рисования графики в любой среде разработки, достаточно почитать документацию с пол-часа.
На фоне всего этого про Canvas периодически пишут статьи, в которых Canvas подается как новая крутая технология а не в духе «основы программирования для чайников».
Та же тенденция наблюдалась и в других случаях веб-разработки: «революционный» json (мы можем просто перечислить поля объекта через запятую!), прорывной Ajax (мы можем запросить данные с сервера!), REST…
Я к чему это все. Уважаемые начинающие веб-программисты, поймите, что вещи уровня Canvas, Json, Ajax — это очень очень просто и очевидно. Важность и новизна подобных «технологий» заключалась в том, чтобы ввести их в браузер, который является достоянием всего человечества. Сами по себе они тривиальны.EpicLegend_gg Автор
12.01.2019 14:34Так а кто спорит? Я полностью с вами согласен.
Нет на ру сегменте нормального образования.(ну или я их не встречал) За основы программирования подаются переменные, функции, ветвление, циклы.
Zenitchik
12.01.2019 14:47+1Важность и новизна подобных «технологий» заключалась в том, чтобы ввести их в браузер, который является достоянием всего человечества
Так статьи и пишутся про их реализацию в браузере. Будь они хоть трижды тривиальны, но чтобы применить конкретную их реализацию — нужно знать API пресловутой реализации.
То же самое могу сказать об Ajax.
Что же касается данной конкретной статьи — ценность её нулевая, потому что то же самое легко находится поиском по Хабру, причём лучше написанное (и, что характерно, очень давно).
StrangerInTheKy
12.01.2019 15:35+1opacity — скорость с которой наши элементы будут затираться на canvas'e
Opacity — это непрозрачность, а не скорость.
set
12.01.2019 16:46fps — думаю объяснять не нужно для чего… правда работает странно…
Думаю, объяснять надо. Я так и не понял, где именно используется это свойство. Оно объявлено, но нигде не вызывается.
ctx.fillStyle позволяет задать цвет заливки, а ctx.fillRect(точка x, точка y, ширина, высота) позволяет нарисовать фигуру. Задаем рандомную высоту с шириной, но в диапазоне наших размеров.
В описании вы говорите о задании рандомных размеров, но ведь в коде написаны рандомные координаты, но статичные размеры. Где ошибка-то? В описании или в реализации?
Bhudh
13.01.2019 01:32Просто во фразе «Задаем рандомную высоту с шириной» автором разумеются координата x («ширина») и координата y («высота»).
set
13.01.2019 12:39Простите, но зачем же подменять понятия? Ведь в цитируемом сообщении автор изначально указывает, какие свойства передаются методу и в какой очерёдности — «точка x, точка y, ширина, высота». И практически сразу же пишет о рандомной ширине и высоте.
sfi0zy
Думаю лучше все-таки в статьи вставлять код в виде кода, а не картинками.
Maklaud
Код в виде кода скопируют и забудут, а с картинки придется напечатать вручную — лучше усвоится :)
Пример с гравитацией просто офигенный, автор молодец!
StrangerInTheKy
Код на картинке нельзя найти по ctrl+F!
Читаешь-читаешь длинную статью, потом в конце статьи «а помните в начале мы использовали функцию my_stupid_function_on_picture»… Да-да, помню, сейчас пролистаю наверх и прочитаю все надписи на картинках еще раз, но очень-очень внимательно…
EpicLegend_gg Автор
Сужу по себе, код из статьи я копирую… я не пишу его сам. А потом и удивляюсь… а почему я не понимаю то, что я якобы написал… Вот из-за этого и картинки вставил.
AngReload
На некоторых числах
if(options.hue == 360) options.hue = 0;
никогда не выполнится, надо использовать>=
.И это условие должно идти после сложения.
Цвет в любом случае меняется, hue == 361 будет интерпретирован как hue == 1, но всё-таки это ошибка.
Лучше использовать остаток от деления:
EpicLegend_gg Автор
Спасибо. Насчет >= верно(эта погрешность осталась от того момента, когда я использовал целые числа), но % здесь не нужен. Да и менять перед проверкой также лишнее т.к. результат будет идентичный тому, который есть сейчас.