Если вы изучаете веб совсем недавно, но уже успели увидеть различные красивые эффекты на сайте, по типу системы частиц или какие либо игры разработанные на canvas'e и вас это заинтриговало, но изучать что-то новое очень страшно, то я вам готов продемонстрировать, как за 50 строк js кода можно сделать что-то интересное на canvas'e.

image

Скажу сразу, я хочу объяснить логику работы с canvas'ом. Код очень простой, я надеюсь, это подтолкнет вас к изучению такого инструментария как canvas. А так же это очень хорошая практика для начинающего JS программиста.

Перейдем к коду. Напишем простую генерацию квадратов разного цвета на полотне. Код вы можете увидеть сразу весь, далее я объясню его.


Что нам нужно сделать?

  1. Получить canvas и его 2D контекст (Если вы раньше не делали подобного, то не переживайте, это делает 2-мя строчками кода)
  2. Сделаем наш канвас немного адаптивным
  3. Зададим нужные нам переменные и свойства
  4. Отрисовка элемента на canvas'e
  5. При ресайзе меняем размер канваса

Работу в canvas можно разделить на 3 этапа.

  1. Настройка нужных нам свойств (толщина пера, цвет заливки, цвет линии и прочие свойства)
  2. Рисуем элемент
  3. Если мы делаем что-то динамическое. Например, игру, анимацию, систему частиц и прочие элементы, то создаем цикл и в него закидываем рендер (отрисовку) наших объектов

Ну хорошо, вернемся к нашему коду.

1. Как я и говорил, две строчки кода и мы можем манипулировать полотном

image

Получить элемент по Id это стандартный API браузера, а вот getContext это метод самого canvas'a. Можно получить и 3D контекст, но в данный момент он нам не нужен.

2. Второй пункт, третий и пятый я объединю т.к. идет объявление переменных + код здесь одинаковый. Можно даже сделать отдельную функцию т.к. уже идет дублирование кода, а это плохо.

image

Переменные width и height нам потребуются дальше.Также не забудьте вызвать функцию ReSize после получения контекста canvas'а.

Нам потребуется еще объект options. В нем мы будем хранить все настройки.

opacity — скорость с которой наши элементы будут затираться на canvas'e
count — количество кубов, которые мы будем создавать за один прогон функции
fps — думаю объяснять не нужно для чего… правда работает странно…
color — здесь лежит маска, которая представляет нашу цветовую палитру
hue — это цветовой тон в диапазоне от 0 до 360. На картинку будет понятней

image

divisionSpeed — это переменная с помощью которой мы сможем регулировать скорость смены цвета

image

4. Нам остается лишь создать цикл, функцию для отрисовки и вызвать всё это.

image

Создаем функцию 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)


  1. sfi0zy
    11.01.2019 20:39

    Думаю лучше все-таки в статьи вставлять код в виде кода, а не картинками.


    1. Maklaud
      11.01.2019 22:04

      Код в виде кода скопируют и забудут, а с картинки придется напечатать вручную — лучше усвоится :)

      Пример с гравитацией просто офигенный, автор молодец!


      1. StrangerInTheKy
        12.01.2019 15:38
        +1

        Код на картинке нельзя найти по ctrl+F!
        Читаешь-читаешь длинную статью, потом в конце статьи «а помните в начале мы использовали функцию my_stupid_function_on_picture»… Да-да, помню, сейчас пролистаю наверх и прочитаю все надписи на картинках еще раз, но очень-очень внимательно…


    1. EpicLegend_gg Автор
      12.01.2019 10:57

      Сужу по себе, код из статьи я копирую… я не пишу его сам. А потом и удивляюсь… а почему я не понимаю то, что я якобы написал… Вот из-за этого и картинки вставил.


      1. AngReload
        12.01.2019 11:39

        На некоторых числах if(options.hue == 360) options.hue = 0; никогда не выполнится, надо использовать >=.
        И это условие должно идти после сложения.
        Цвет в любом случае меняется, hue == 361 будет интерпретирован как hue == 1, но всё-таки это ошибка.
        Лучше использовать остаток от деления:


        options.hue += 1 / options.divisionSpeed;
        options.hue %= 360;


        1. EpicLegend_gg Автор
          12.01.2019 13:03

          Спасибо. Насчет >= верно(эта погрешность осталась от того момента, когда я использовал целые числа), но % здесь не нужен. Да и менять перед проверкой также лишнее т.к. результат будет идентичный тому, который есть сейчас.


  1. Zenitchik
    11.01.2019 22:57

    Переменные width и height нам потребуются дальше.

    В глобальном пространстве имён? Вы серьёзно?

    Также не забудьте вызвать функцию ReSize после получения контекста canvas'а.

    Зачем? Она же не работает с контекстом.


    1. EpicLegend_gg Автор
      12.01.2019 10:55

      Я не пишу библиотеку, которой потом «возможно» будут пользоваться. Это простой пример. Лучше допускать ошибки, чем не писать вовсе код.

      ReSize нужно один раз вызвать перед основным циклом т.к. он установит нужные размеры канвасу и обновит значения переменных width и height


      1. Zenitchik
        12.01.2019 14:43
        +1

        Это простой пример.

        Сразу содержащий плохой пример…

        Лучше допускать ошибки, чем не писать вовсе код.

        Как PET-проект — может быть, но не как совет другим.

        ReSize нужно один раз вызвать перед основным циклом

        Именно, и это не обязательно
        после получения контекста canvas'а.


        Я лично рекомендую его запускать сразу после загрузки страницы.


        1. Keyten
          12.01.2019 15:45

          Да не так уж и плохо, например в jsfiddle в маленьких демках тоже вполне допустимо юзать глобальные переменные типа width / height.


  1. tamerlan676
    12.01.2019 10:52

    На сервисе udacity есть курс по Canvas. Вполне себе достойный.


    1. babylon
      13.01.2019 10:41

      Что ещё можно делать на Canvas чего нельзя делать с SVG?



  1. muhaa
    12.01.2019 13:05
    +7

    Если вас заинтересовал canvas, то самое время продолжить изучение этой технологии.

    1. Функции для рисования графики были и есть в любой мало-мальски развитой среде разработки, начиная с бейсика или Турбо-паскаля в 80-ых.
    2. Эти функции для рисования во всех средах реализуются почти одинаковым и очевидным образом, Canvas — не исключение.
    3. Для освоения функций рисования графики в любой среде разработки, достаточно почитать документацию с пол-часа.
    На фоне всего этого про Canvas периодически пишут статьи, в которых Canvas подается как новая крутая технология а не в духе «основы программирования для чайников».
    Та же тенденция наблюдалась и в других случаях веб-разработки: «революционный» json (мы можем просто перечислить поля объекта через запятую!), прорывной Ajax (мы можем запросить данные с сервера!), REST…

    Я к чему это все. Уважаемые начинающие веб-программисты, поймите, что вещи уровня Canvas, Json, Ajax — это очень очень просто и очевидно. Важность и новизна подобных «технологий» заключалась в том, чтобы ввести их в браузер, который является достоянием всего человечества. Сами по себе они тривиальны.


    1. EpicLegend_gg Автор
      12.01.2019 14:34

      Так а кто спорит? Я полностью с вами согласен.
      Нет на ру сегменте нормального образования.(ну или я их не встречал) За основы программирования подаются переменные, функции, ветвление, циклы.


    1. Zenitchik
      12.01.2019 14:47
      +1

      Важность и новизна подобных «технологий» заключалась в том, чтобы ввести их в браузер, который является достоянием всего человечества

      Так статьи и пишутся про их реализацию в браузере. Будь они хоть трижды тривиальны, но чтобы применить конкретную их реализацию — нужно знать API пресловутой реализации.
      То же самое могу сказать об Ajax.

      Что же касается данной конкретной статьи — ценность её нулевая, потому что то же самое легко находится поиском по Хабру, причём лучше написанное (и, что характерно, очень давно).


  1. StrangerInTheKy
    12.01.2019 15:35
    +1

    opacity — скорость с которой наши элементы будут затираться на canvas'e
    Opacity — это непрозрачность, а не скорость.


  1. set
    12.01.2019 16:46

    fps — думаю объяснять не нужно для чего… правда работает странно…

    Думаю, объяснять надо. Я так и не понял, где именно используется это свойство. Оно объявлено, но нигде не вызывается.

    ctx.fillStyle позволяет задать цвет заливки, а ctx.fillRect(точка x, точка y, ширина, высота) позволяет нарисовать фигуру. Задаем рандомную высоту с шириной, но в диапазоне наших размеров.

    В описании вы говорите о задании рандомных размеров, но ведь в коде написаны рандомные координаты, но статичные размеры. Где ошибка-то? В описании или в реализации?


    1. Bhudh
      13.01.2019 01:32

      Просто во фразе «Задаем рандомную высоту с шириной» автором разумеются координата x («ширина») и координата y («высота»).


      1. set
        13.01.2019 12:39

        Простите, но зачем же подменять понятия? Ведь в цитируемом сообщении автор изначально указывает, какие свойства передаются методу и в какой очерёдности — «точка x, точка y, ширина, высота». И практически сразу же пишет о рандомной ширине и высоте.