Анимация падающего снега на Canvas эффективнее анимации на DOM в несколько раз

в 5:24, , рубрики: canvas, javascript, snowfall, snowflakes, Алгоритмы, анимация, метки:

.Анимация падающего снега на Canvas эффективнее анимации на DOM в несколько раз - 1В сравнении с нативным JS на элементах DOM, реализация анимационных алгоритмов на Canvas обычно производительнее во много раз. Это известный факт (но с особенностями для малого числа частиц, как выяснится позже), и он может найти реализацию так всем мешающего традиционного под НГ, но гонимого рациональными пользователями «падающего снега». Чтобы нагрузки было мало, в последние годы считается хорошим тоном «запускать» снег на сайте едва заметным, с минимальным количеством снежинок (5-15). Тут и эффект есть, и нагрузки на процессор почти никакой.

Поэтому, пока до НГ ещё несколько дней ещё зима, предлагаю устроить хакатончик по реализации лучших алгоритмов на канвасе и их аналогов на DOM, взяв за основу в основном древние нативные алгоритмы, которые как максимум обёртывались в плагин jQuery, чтобы было удобно подключать. Большая часть этих алгоритмов не соразмеряет нагрузку на процессор или сделана неэффективно, поэтому даже при малом числе снежинок грузят процессор на 100%. Вот пример обзорной статьи, где рассмотрены более 10 реализаций, не все, встречающиеся в природе. В дополнение, рассмотрим несколько избранных, чтобы получить задел на развитие алгоритма и реализацию его с хорошей эффективностью (получится ещё 5-6 вариантов). На этой основе можно построить доработку.

Как обычно, жизнь статьи на Хабре не длится более 1.5 дней, поэтому нельзя рассчитывать акцию эффективной. Но после Нового Года случаются разные чудеса: поток посетителей падает, и случайные лунатики получают шанс не забыть одну статью целых 5 дней. На них и делается ставка.

Лучше если она будет привязана к длительному процессу, например, к клубу Анонимных Дедов Морозов, заходя в который всегда можно будет получить привязку к обсуждению и развитию вариантов «падения снега» и при этом он не привязан жёстко к празднику. Результат в настоящее время — здесь: geekadm.ru/#/2015, и есть, конечно, промежуточные эксперименты типа 46.101.141.171/snow.html?v=4 — снег для HabraAdm с дополнительными эффектами.

Предварительный «хакатон» был устроен парой участников и (или) посетителей клуба — (1), (2). В результате, получилось до 10 вариантов на движке с Canvas. Их число может быть намного больше, но на всё нужно свободное время, поэтому акция превратилась в открытую. Например, можно «прикрутить» к движку уже написанную в 2003 году модель падения снежинок автором Peter Gehrig. Доработка в 2005-2006 показывает на современных браузерах, что 20-30 снежинок незначительно нагружает процессор (10-20%, зависит от мощности и видеокарты; здесь и далее будем говорить о загрузке одного ядра процессора, т.к. JS — однопоточный), а по свидетельствам старых форумов, подобное было и на старых браузерах типа Opera 9 и IE6, но несколько хуже. На Canvas с тем же алгоритмом можно было бы запускать раз в 5 больше объектов.

Анимация падающего снега на Canvas эффективнее анимации на DOM в несколько раз - 2

демо

Анимация падающего снега на Canvas эффективнее анимации на DOM в несколько раз - 3

Заглянем в историю и посмотрим на её ход

Давайте начнём с начала, с 2002-2005 годов примерно. Джаваскрипт показал способность анимировать падение снежинок. Правда, оказалось, и это было естественным, анимация на скрипте или непроизводительная, или сильно грузит процессор. Поэтому и в те старые времена нужно было или очень экономить ресурсы, или грузить процессор по максимуму, на 100% в потоке браузера, (на 1 ядре) что тормозило другие вкладки (в тех браузерах типа Оперы 9, где они были) и окна, и это вызывало плохо скрываемое негодование посетителей таких страниц.

Через лет 8 нашлось решение этой проблемы на уровне браузера. Основные браузеры, начиная с Хрома, стали приостанавливать выполнение скриптов на невидимых вкладках. Это помогло не мешать просмотру других окон и программ (но не приостанавливается при переходе на другое окно, а только уменьшается нагрузка, если окно не отрисовывается на экране или видно частично). Правда, в связи с мобильной эрой, открывание страниц с грузящей анимацией, всё равно, не воспринимается положительно.

Но за эти годы появился и более совершенный механизм анимации — Canvas. Сразу надо заметить, что другой новаторский механизм — анимации в CSS — не помогают экономить нагрузку, и тратят энергию процессора ровно столько же, как и анимация на Javascript + DOM. То есть, если искать лучшее решение, то приходится делать это в Canvas.

Canvas, как это будет видно в примерах, позволяет сотню снежинок запустить с нагрузкой 30-40% для среднего настольного компьютера или ноутбука. Это примерно в 5 раз эффективнее, чем умеют лучшие оптимизированные алгоритмы на JS+DOM.

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

Очень много алгоритмов легко найти поиском в Github по словам типа «snowfall js», «snow flakes js». Они дополнят хорошую подборку из 12 скриптов с демо-ссылками, упомянутую выше (или расширенная копия).

Обзор алгоритмов с примерами

(При просмотре страниц с примерами будьте готовы к иногда 100%-ной загрузке ядра процессора. При показе ссылки в статье об уровне загрузки предупреждается.)

Многие алгоритмы, кроме того, что неэффективны, ещё и не похожи по поведению на реальное поведение снежинок. Наверное, многим помнится бросающееся в глаза несоответствие реальности движение снежинок по синусоиде. Однажды увиденное (или новее), оно запоминается надолго в качестве отрицательного примера. Поэтому, задача алгоритма — быть не только эффективным, но и отражающим реальность. (По эффективности, вычисление гармонических функций тоже должно проигрывать.)

Из ранее пересмотренных алгоритмов наиболее близкими к реальности можно считать два — со случайными перемещениями (варьировать надо скорости, а не координаты) и упомянутый алгоритм Peter Gehrig (2003), в котором движение управляется 4 переменными, и одна из них — гармонически изменяющаяся, что создаёт периодические эффекты «завихрений». Впрочем, по этому поводу можно спорить и добавлять в копилку новые реализации.

Из найденных реализаций алгоритма P.Gehrig нашлась страничка с примером: www.softtime.ru/javascript/snow-falling.html. По ней понятно, о чём идёт речь. Небольшое количество снежинок (15-20) и сейчас не сильно грузит процессоры (10-20% для не слабых ноутов), работает в Хроме и Firefox, хотя в списке поддержки читается Opera 9, IE5 и 6 и какой-то ранний Firefox. Разумеется, о Canvas тогда не знали.

Сведём увиденное в таблицу, где покажем:
*) количество частиц;
*) тип анимации;
*) наличие песочницы для экспериментов;
*) загрузка процессора (MacBook, Firefox 43) (Хром обычно % на 10 эффективнее);
*) комментарии об особенностях.

(Реальные данные загрузки процессора будут отличаться от указанных для разных компьютеров, для компьютеров с разными видеокартами и для мобильных устройств в широких пределах. Даны для ориентировки для среднемощного ноутбука со встроенной графикой.)

Посмотрим быстрее на скрипты с применением Canvas.

Не чистый JS Демо: 400x400, Snowman with Falling Snow
Частиц на демо: 100
Анимация падающего снега на Canvas эффективнее анимации на DOM в несколько раз - 4
Тип: Canvas
Песочница — ДА
Загрузка: 70%
Строк кода: 106 +ProcessingJS (800K)
Рисуется в среде ProcessingJS на 800К несжатого кода, создающей язык типа «Рапира». Снеговик рисуется тем же кодом. Пример — особый. Показывает, что с оболочками наворотить можно чего угодно (для решения простых задач сложными способами), и даже в этом случае Canvas не катастрофически проигрывает решениям на DOM.
Статья (en), 2012 Код: Github Демо: весь экран
Частиц на демо: 500
Анимация падающего снега на Canvas эффективнее анимации на DOM в несколько раз - 5
Тип: Canvas
Песочница? Нет
Загрузка: 100%
Строк кода: 50 + 100 в *.html +ThreeCanvasJS (72K)
72 К сжатого неупакованного кода библиотеки ThreeCanvas.js. 3D-сцена с вращением её движением мыши. Здесь ради плавного движения поставлен малый битрейт, поэтому всё красиво, но как фоновое действие — не слишком подходяще.
Год: 2010 Код: JS Демо и описание: весь экран
Частиц на демо: 60, крутятся в плоскости рисунка
Анимация падающего снега на Canvas эффективнее анимации на DOM в несколько раз - 6
Тип: Canvas
Песочница? Нет
Загрузка: 100%
Строк кода: 160
Очень частая анимация не позволяет и здесь оценить достоинства Canvas. Есть вращение рисованых снежинок вокруг своей оси, медленное падение с блужданиями. Но часть из них «ходит» по синусоидам, кручение в одной плоскости нисколько не придаёт реалистичности, что, наоборот, отторгает от восприятия эффекта, создаёт, скорее, эффект назойливости. Код — наоборот, показывает свою мощность и компактность. В сумме — отличные усилия направлены на достижение немного не тех эффектов, что для потребителя — ничем не лучше поедающих энергию движков на DOM.
 
  Посмотрим на примеры скриптов, работающих с DOM (слоями), без Canvas.

Год: 2009 Демо: jSnow – jQuery Snow Effect, весь экран Код: JS (несжатый прежней версии)
Частиц на демо: 25
Анимация падающего снега на Canvas эффективнее анимации на DOM в несколько раз - 7
Тип: DOM
Песочница? Нет
Загрузка: 70%
Строк кода: 160 + jQuery
Варианты в песочницах Fiddle (везде используются символьные снежинки):

  • Упакованный (обфусцированный) оригинальный код в песочнице с адаптацией к jQuery 2.
  • Распакованный, но плохо движущийся (малые синусоиды) мод mod1 кода в песочнице с адаптацией к jQuery 2.
  • Восстановленный с рефакторингом имён, стиля, максимально похожий и работающий код (Fiddle) этого скрипта в песочнице. Останавливается/запускается по кнопке останова. В сжатом виде — 1.5К.
  • Расширенный до возможности запуска нескольких объектов в блоках или в целом окне. Запуск по коллекции. В сжатом виде — 1.8 К, меньше оригинального, который 2.2-2.4 для разных модов.
У этого скрипта — характерный почерк движений частиц (сильно в стороны). Если присмотреться — это просто очень большие синусоиды, воспринимающиеся как один большой вихрь посередине окна. Он очень сдержан по трате ресурсов. Исходный код версии 1.2 — утерян или всегда был обфусцирован пакером; распакованные версии 1.1.mod2 (доработанные другими авторами) — есть в песочнице Codepen, но не работают с новыми jQuery, потому что обращаются к отменённым $.browser. И в них видны следы распаковки. Прекрасно смотрится в невысоких заголовках (пример), когда синусоиды не успевают проглядеться. Из десятков примеров, если стоит приглядеться к паре из них (по исполнению и коду), то этот пример — один из них. Поэтому за версию jSnow возьмёмся основательно, запустив в песочнице.

Что интересно, упакованная версия автора, 1.1 или 1.2 работает заметно быстрее — при тех же внешних настройках нагружает процессор на 40%, а 1.1.mod2 — на 55%. (Фиддл тоже быстрее работает не в многооконном режиме.) Скорее всего, так сказываются лишние проверки в цикле отрисовки снежинок (в модах добавлены «фичи»). Сам код не предельно оптимизирован — пишет инлайновые стили, которые можно задать правилами.

Далее стало интереснее — в коде при тестируемых настройках обнаружился ряд багов (и это не значит, что нашлись все). Кое-какие правки в коде делать придётся (убрать несовместимость с jQ 2+, вычисление начального положения снежинки, не давать заходить им за левый край окна — в маках это приводит к «вспыхиванию» полосы прокрутки, и полезно то же самое делать для нижней границы), поэтому пользоваться лучше модифицированными современными версиями.

Версии-моды (2009-2010) добавили пару насущных «фич» — настройки плавного исчезания снежинок внизу (fadeAway: 1) и возможность прокрутки с неперемещением поля снежинок (followScroll: 1). Названия оставлены оригинальными, какими назвали их разработчики.

Цель отладки старого кода в том, чтобы потом алгоритм перенести на Canvas и сравнить скорости. (Калек побеждать — чести маловато.) В настройках я повторяю те же ошибки, над которыми критиковал других. Для разработчика неважно, что разноцветный снег, падающий в 2D, не бывает — главное, есть техническая возможность раскрасить. А ещё, летят не снежинки, а комки в реальности. Но 3/4 населения Земли этого не знает, так что нас ждёт успех… В наборе снежинок использовано большинство символов Unicode, похожих на снежинки — набралось аж 8. Можно найти ещё столько же.

Итак, получился читаемый код, на 20 строчек короче (90 строк) и в упакованном виде на 30% меньше (1.5К), чем лучшие образцы модов, не потеряв при этом функций и добавив стоп-старт-кнопку. Этот промежуточный вариант компактен, но работает, как и раньше, с окном и абсолютно может задавать высоту (height: число) в параметрах. Это не очень удобно, тем более, что плагин не использует контекстную коллекцию вообще, поэтому нормально себя чувствует с вызовом странного вида $().jSnow(...), т.е. без контекста. Получилось довольно просто, ограничимся здесь ссылкой на демо.

И усложним задачу — начать работать с контекстными коллекциями jQuery. Сохраним это поведение, когда нет контекста — выбираем работу с окном, как и при контексте window и $('body')) и добавим работу с блоком-контейнером (например, запускать по $('.contSnow').jSnow(...) ). Контейнер придётся подготовить, для него нужен position:relative, чтобы вставляемый блок с absolute хорошо себя чувствовал. Блок, который на всё окно, тоже начнёт себя вести по-другому, будет покрывать окно, поэтому весь контент страницы потребуется поднять, если будет такой блок. (Можно и иначе, по-старому, но зачем усложнять? Скорее, будут использовать или первый скрипт, или второй.) Получится примерно так:

Анимация падающего снега на Canvas эффективнее анимации на DOM в несколько раз - 8

демо, (код в репо). Это DOM, нагрузка 30% на поток (15% — общая) с битрейтом 12.
Несколько влияет то, что картинки — крупные и прозрачные.

В самом деле, зачем работать только с одним контейнером, если jQuery может предоставить коллекцию? Получается что-то типа такого, нагрузка 30-50% для суммы в 70-120 частиц. Остановку-запуск можно тоже разделить по кнопкам или сделать общей.

При попытках применить написанное сразу бросается в глаза непрактичность запуска скрипта на коллекции. Запустить — да, можно, даже десятки инстансов скриптов, раздавая каждому по чуть-чуть снежинок. Но всем блокам коллекции сообщаются одинаковые параметры, и это — непрактично, т.к. чаще хочется сделать другую задачу — запустить немного окон (виртуальных, на дивах), но с разными параметрами, а для этого приходится их сообщать одному элементу. Получается, чаще всего, что сколько элементов, столько нужно запусков .jSnow, что получается длинно, хотя и наглядно.

Тут возникает аналогия с написанием правил CSS. Правила — это те же декларации параметров, какие мы делаем при запусках плагинов, даже селекторы у плагинов стоят на своём месте. Но нет сейчас механизам постепенно накапливать описания правил (подобно тому, как в одном — font-size, в другом — position). Второй запуск плагина на том же элементе добавляет ещё один инстанс плагина (долгоиграющую функцию с замыканием и возможностью выключения), а не добавляет свойств к уже запущенному. При этом удобнее было бы перечислять селекторы (просто строки с классами), а не JSON-ы настроек. Но не припомнится ни одного плагина, где такой способ конструирования настроек был бы нужен и работал. На самом продвинутом варианте демо напишем запуск в 4 областях так, как плагин теперь умеет:

Анимация падающего снега на Canvas эффективнее анимации на DOM в несколько раз - 9

демо, (кот в репо)

Доработки плагина добавили порядка 300 байт сжатого кода, но теперь он с бОльшим основанием может называться плагином. Правда, без единого метода.

Другие скрипты для работы с DOM

Такое внимание уделено одному скрипту, не самому продвинутому, потому что, если заглянуть вперёд, он оказывается небольшим конкурентом скриптам на Canvas, не тем, что выше, а хорошо, экономично написанным. Неэффективно написанные не станут конкурентами, поэтому в коде нельзя допустить ничего лишнего, чтобы было что с чем сравнивать.

Например, есть очень популярный скрипт на DOM под названием Snowstorm, со сжатым кодом 20К, очень большим количеством настроек, отключением в мобильных устройствах — есть, чему поучиться и для малых скриптов. Но изучать, что там лишнего и приводит ли это к потерям — слишком сложная задача. Проще написать малое и расширять настройки. Значимость каждой выяснится на тестах и практике.

Быстро пройдёмся по ещё одному небольшому скрипту, который не найден среди хорошо оформленных демо и песочниц, но имеет интересное поведение (упоминался выше, автора P.Gehrig). Нет больших сложностей поместить его в песочницу — доработок багов не требует, jQuery не использует, но потребовалось приучить к современному доктайпу. Также, раньше было плохо с особыми символами Unicode у системных шрифтов, сейчас — лучше, поэтому падающие буквы заменены на падающие текстоваые (подцвеченные) снежинки.

Год: 2005, falling-snow с настройками, код, jsFiddle
Частиц на демо: 25 Анимация падающего снега на Canvas эффективнее анимации на DOM в несколько раз - 10
Тип: DOM
Песочница? ДА
Загрузка: 10% (из-за 8 FPS)
Строк кода: 90
Столь малая загрузка системы у оригинальных настроек скрипта вызвана низким выставленным FPS. Это, конечно, заметно по движениям как частое слайдшоу. Это было нужно для старых браузеров и предупреждается в старых комментариях к скрипту. При 30 FPS — загрузка 35%, примерно столько же, как будет у предыдущего скрипта при таких же настройках.

У этого скрипта есть модификация с добавлением броуновского движения и с падением как бы «издалека» экрана, увеличением и «таянием» (увеличением прозрачности) вблизи или внизу.

Год: 2006, falling-snow с падением «издали» с настройками, jsFiddle
Частиц на демо: 25 Анимация падающего снега на Canvas эффективнее анимации на DOM в несколько раз - 11
(смотреть в полном экране)
Тип: DOM
Песочница? ДА
Загрузка в jsFiddle: 60% (16 FPS)
Строк кода: 100
Здесь настройки размеров достаточно «капризны» — небольшим изменением скорости роста можно получить огромные снежинки или не растущие, поэтому другие сценарии поведения нужно подбирать, а эффектность будет зависеть в конечном итоге от размеров окна и поведения (не автонастраивается). Заметное повышение нагрузки связано с отрисовной больших прозрачных символов (изображений). (Исходный код написан плотно, реальное количество кода после разреживания было бы в 2 раза больше.)

Напишем все варианты кода со снегом на Гитхабе. Учтём недоработки предшественников, которые не писали демо-страниц, и потому на их код посмотрели гораздо меньше людей. Гитхаб позволяет крайне просто запускать демо, если работать в ветке gh-pages. Теперь все модификации версий легко фиксируются в истории изменений и смотрятся различия. Гитхаб: github.com/spmbt/snowfalls.

Как там с CSS-анимациями?

Смотрим примеры, написанные другими, дальше, в поисках эффективных алгоритмов и эффектных результатов.

1. Пример (единственный с анимациями CSS) сильно загружающей анимации на CSS3 с вращением DOM-снежинок — www.jqueryscript.net/animation/jQuery-Plugin-For-Snowfall-Effect-with-Rotating-Snowflakes.html. (На этом сайте есть всё — описание, код и демо для каждого скрипта, но без песочниц.)

2. Анимация на 3 картиночных слоях в CSS (Codepen).

Пробуем смотреть ещё анимации на канвасе, чтобы найти не сильно нагружающий систему скрипт.

Пример анимации на Canvas, активирующейся по движению мыши, где можно увидеть, что приемлемое количество снежинок — не сплошная генерация с порядка 200-300, а порядка 50-100 на экране — www.jqueryscript.net/animation/Yet-Another-Falling-Snow-Animation-with-jQuery-Canvas-GlauserChristmas.html.

Ещё одна анимация на Canvas без библиотек, с демо и комментариями на китайском: www.jqueryscript.net/animation/Nice-Snow-Falling-Effect-with-jQuery-Canvas-Nice-Snowing.html.

Все эти анимации, включая Canvas, почему-то настроены так, что грузят процессор на 100% (точнее, одно ядро, которое может загрузить однопоточный JS). Это будто бы считается нормальным для демонстраций скриптов. (Возможно, на дискретных видеокартах это так и есть.)

Как-то это всё странно

Среди скриптов со снегом встречается очень мало экономящих нагрузку процессора, хотя они есть как для DOM, так и для Canvas. Покажем, что того же эффекта полной загрузки можно добиться не для 100, а для пары тысяч снежинок, а нормальной лучше считать загрузку ядра на 10-20% для 200-400 штук.

Выбираем эффективный Canvas

Впрочем, тут нашёлся один экономичный скрипт на чистом Canvas. Свои примеры будем делать примерно в его стиле.

Год: 2015 Демо: Snow Effect using HTML5 Canvas and Javascript, весь экран Копия на jsFiddle
Частиц на демо: 25
Анимация падающего снега на Canvas эффективнее анимации на DOM в несколько раз - 12
Тип: Canvas
Песочница — ДА
Загрузка: 45%
Строк кода: 90
Пример показывает, что если мы контролируем весь код, который не делает ничего лишнего, как это происходит в примерах выше, то успех близок. Нагрузка даже с 200 частицами (в Хроме) составляет 45% (нужно смотреть 2 или 3 процесса — Chrome и два Chrome helper) и 60% при 2000. Для Firefox — примерно то же, разве что на 10% медленнее (при хороших условиях) и больше случайных тормозящих факторов.

Но проблемен Canvas при малых нагрузках. Нагрузка при 2 частицах часто составляет 40-60% и столько же — для 25, и 0 — для незапущенного setInterval(). Любая его дорисовка нагружает процессор (при 30 FPS — процентов от 30), а объём дорисовки не имеет большого значения. Очевидно, что при худшей видеокарте результаты будут хуже, и где-то мы перестанем видеть улучшения, тормозить начнёт всегда при наличии Canvas, а поправить можно будет только уменьшением FPS.

Более детально, результаты такие. Берём jsFiddle как менее влияющий на результаты, копируем туда пример с добавлением кнопки остановки. Запускаем разное количество снежинок, ждём примерно минуту, пока расходы процессора успокаиваются (не двигая мышь, ничего не делая). Смотрим результаты через Activity Monitor (MacBook с видео Intel HD Graphics 5000). Если смотреть на Windows, скажем, на 4-ядерном процессоре, то увидим загрузку не более 25%. Называемые здесь в статье 100% относятся к загрузке одного ядра, т.е. 25% надо будет умножать на 4. Просто браузеры пока по-другому не умеют распараллеливаться, но и эта нагрузка для ноутбука достаточно чувствительна, приводит к расходу энергии, приблизительно как при просмотре видео.

Незапущенная отрисовка -10% нагрузки (фон).
0 частиц — 30%;
2 частиы — 35%;
25 частиц — 40%;
200 частиц — 50%;
1000 — 55%;
2000 — 65%.
При этом не всегда показания повторяются, зависит от других запущенных программ и занятости памяти.

Вот и разгадка того, почему с появлением Canvas все сразу не бросились программировать на нём. Процессоры, начальное возможное несовершенство реализации и неполная поддержка в браузерах не позволяли делать приемлемый битрейт, чтобы с хорошим качеством движения пройти «ценз производительности», зависящий не от числа частиц, а от битрейта, и уложиться при этом в идеале в 20%. С анимацией на слоях можно запустить хотя бы 5 частиц и пройти этот ценз. Сейчас с производительностью стало лучше, а IE8, который без Canvas, занимает долю около 0.5 процента.

Свои алгоритмы на канвасе

Создадим свои варианты экономичных алгоритмов на канвасе. Сначала замкнём плоскость в тор и пустим снежинки по ветру с небольшими случайными блужданиями, которые применяются к скорости каждой частицы. Получается довольно естественно, хотя без впечатления о порывах ветра. Второй эффект — параллакс, когда более мелкие частицы падают медленнее, что создаёт ощущение трёхмерности сцены.

С такими установками пошёл первый блин.

Год: 2015 Демо и песочница: ветер с падением и случайными блужданиями скорости, весь экран, завёрнутый в тор
Частиц на демо: 100
Анимация падающего снега на Canvas эффективнее анимации на DOM в несколько раз - 13
Тип: Canvas
Песочница — ДА
Загрузка: 35%
Строк кода: 50
Случайность блужданий приводит к тому, что некоторые частицы, довольно большое их число, летят, постепенно меняя направление и летают всё более произвольно. Нужно «затухание» отклонений скорости, чтобы рой частиц приводился к общему потоку. Множитель *.999 в коде создаёт это «успокаивание». Но действует на скорость вообще, поэтому со временем они будут всё больше замедляться. Для бесконечного падения это не подходит, но нужно падение в пределах экрана.

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

Демо 2 и песочница: Сцена с таянием снега внизу окна, весь экран
Частиц на демо: 1000
Анимация падающего снега на Canvas эффективнее анимации на DOM в несколько раз - 14
Тип: Canvas
Песочница — ДА
Загрузка: 40-50% (30 FPS)
Строк кода: 50
Величина частиц влияет на то, где они будут останавливаться: чем больше частица, тем ближе к низу окна. Это тоже создаёт эффект трёхмерности и случайное заполнение «земли» снежинками.

Вначале нужно запустить заряд снега помощнее, чтобы быстро образовался покров. Через минуту он на глазах начнёт таять, а полностью растаявшие частицв снизу переходят наверх. Круговорот воды.

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

Скрипты Kafeman в рамках хакатона

Параллельно скрипты со снегом и другими праздничными эффектами делал kafeman.
Начальная идея — построить приветственную страницу с эффектами для посетителей клуба АДМ. Всё могло быть серьёзней, но история не терпит сослагательного наклонения. Кроме чисто декоративного оформления, посетила идея посмотреть на реальный снегопад (1, 2, 3) и смоделировать те неприятные близко мелькающие частицы снега. Совершенство ещё не достигнуто, но направление имеет все основания, иначе не вспомнится лепящийся на лицо отвлекающий снег. Тут надо поэкспериментировать с отрисовкой бесформенных хлопьев и их смазанным мельканием.

И надо как-то отращивать снежный покров: jsfiddle.net/162e4jte/3, но не так, чтобы он поглотил всю планету с космонавтом на ней. Поначалу он тоже ложился бугорками и таял: jsfiddle.net/162e4jte/1. Такое поведение встречалось в скриптах других авторов.

Накоец, на будущее идея объединения генераторов движков в один тоже заслуживает исполнения. По результатам, кроме массы скриптов сторонних авторов, имеем 3-4 алгоритма движения частиц и 2 способа реализации, общие части которых достаточно хорошо по представленным песочницам и репо отслеживаются.

Немного статистики. В связи с глобальным потеплением интерес к снегу в совокупности с Javascript? как и к лыжам — падает, а интерес к Canvas и Javascript — растёт. Теперь мы знаем, в какой комбинации будет обеспечен стабильный интерес.

Заключение

2 реально выполнимых для эффекта снега способа программирования — DOM-слои и Canvas — имеют свои ниши применения. До примерно 50 частиц выигрывает DOM, но не во всех режимах, для задач, где нужна малая нагрузка на процессор. Высокий битрейт понижает планку. Более 50 (но уверенно — более 200) — но тоже с желательно низким битрейтом — выигрывает Canvas. Но раскошеливаться надо на загрузку побольше — от 30% ресурсов процессора. Граница и критерии — очень зыбка и зависит от аппаратуры, браузера, успехов реализаций движка в браузерах. Мобильный пользователь скажет категорическое «нет» более 5 частицам, а стационарник с большой видеокартой искренне не будет понимать, в чём проблемы с 200 частицами в DOM и с 5000 в Canvas.

Всё лишнее из алгоритма для типичного коммерческого применения (внимание пользователя в районе праздников) нужно убирать, тестировать алгоритмы на разных устройствах и принимать решения о нише покрытия пользователей. Могут быть более выигрышная низкобитрейтная иллюминация на Canvas или кратковременные фейерверки на нём же. Не помешает подсказать, какой кнопкой выключить анимацию и запомнить в настройках юзера, что «акция отработала». Поскольку снег не такой денежный, как Яндекс-браузер, нет оснований «ломать» эту кнопку сознательно. Ещё через пару лет можно надеяться, что положение с канвасом улучшится, и он медленно будет отбирать себе область малого количества частиц и повышенного битрейта.

Выразительные возможности скриптов снега, в основном, на данном этапе исчерпаны (ничего качественно нового не появилось в последние годы в этой группе). У достаточно завершённых скриптов есть ряд свойств, признанных необходимыми, а часть невыполнимых по производительности свойств (вращение снежинок в формате 3D) не выполняется, но никого это не смущает. Но из-за производительной отрисовки на канвасе можно ожидать, что такие скрипты появятся (с нагрузкой от 30%).

Перспективы кодирования — можно написать конструкторы, которые давали бы объект для DOM или Canvas по настройкам. Конструкторы могли бы писать разные авторы. С таким подходом организован проект на ХабраАДМе (Гитхаб): github.com/clubadm/snowmachine.

Автор: spmbt

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js