Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Animation
Code

HTML5 Холст оптимизации: практический пример

by
Difficulty:IntermediateLength:LongLanguages:

Russian (Pусский) translation by Shaun Murphy (you can also view the original English article)

Если вы занимаетесь разработкой на JavaScript достаточно долго, вы, скорее всего, разбился Ваш браузер несколько раз. Проблема, как правило, оказывается некоторые JavaScript ошибка, как бесконечный цикл while; если нет, то следующий подозреваемый-страница преобразований или анимации - то, что включает добавление и удаление элементов на веб-странице или анимации CSS свойства. Этот учебник фокусируется на оптимизации анимации производится с помощью JS и HTML5 в элемент .

Этот учебник начинается и заканчивается с тем, что виджет HTML5 анимации, которые вы видите ниже:

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

Исходный файл содержит HTML и JavaScript от каждого шага в учебник, так что вы можете следовать наряду с любой точки.

Давайте сделаем первый шаг.


Шаг 1: играть в кино трейлер

Виджет создан на основе фильма Трейлер Синтел, 3D анимационное кино Фонд блендер. Он построен с использованием двух из самых интересных дополнений в HTML5: на элементе и элементы.

загружает и воспроизводит видеофайл Sintel, а генерирует свою собственную последовательность анимации, делая снимки воспроизводимого видео и смешивая их с текстом и другой графикой. Когда вы нажимаете, чтобы воспроизвести видео, холст оживает с темным фоном, это большая черно-белая копия воспроизводимого видео. Меньше, цветной экран-кадры видео копируются на место, и промелькнет она, как часть пленки рисунке.

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

Наконец, есть большой вращающейся лопасти, которая летает по сцене в начале анимации, графики которых загружается из внешнего файла изображения в формате PNG.


Шаг 2: просмотрите исходный код

Исходный код содержит обычное соединение с HTML, CSS и JavaScript. HTML является негусто: только с помощью и теги, заключенный в контейнер с:

Контейнер присваивается идентификатор (animationWidget), которая выступает в качестве крюка для всех правила CSS применяются к нему и его содержание (ниже).

В то время как HTML и CSS являются маринованные специи и приправы, его в JavaScript, что это мясо виджета.

  • В верхней части, мы имеем основные объекты, которые будут часто использоваться через скрипт, в том числе ссылки на элемент canvas, а ее 2D-контекст.
  • Функция init() вызывается каждый раз, когда видео начинает играть, и устанавливает все объекты, используемые в сценарии.
  • В sampleVideo (функция) отражает текущего кадра воспроизводимого видео, а setBlade() загружает внешние изображения требует анимации.
  • Темпы и содержание анимации контролируются функции main (), которая является как сердцебиение сценария. На регулярной основе, как только видео начинает играть, он рисует каждый кадр анимации, сначала сняв холст, то вызов каждого из пяти функций скрипта рисования:
    • метод drawbackground()
    • drawFilm()
    • drawTitle()
    • drawDescription()
    • drawStats()

Как видно из названий, каждая функция рисования отвечает за рисование элемента в сцене анимации. Структурировать код таким образом повышает гибкость и позволяет в дальнейшем легче.

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


Шаг 3: оптимизация кода: знать правила

Первое правило кодекса оптимизация производительности: нет.

Смысл этого правила заключается в предотвращении оптимизация ради оптимизации, так как процесс происходит по цене.

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

Цель в оптимизации этот виджет будет иметь функции main() выполнить менее чем за 33 миллисекунды, как это предполагается, который будет соответствовать частота кадров воспроизведения видео файлов (синтэл.MP4 и Синтел.формат WebM). Эти файлы были закодированы со скоростью воспроизведения 30 кадров в секунду (тридцати кадров в секунду), что означает примерно 0,33 сек или 33 миллисекунд на Кадр ( 1 секунда ÷ 30 кадров ).

Поскольку JavaScript рисует новый кадр анимации на холст каждый раз, когда функция main() вызывается, цель нашего процесса оптимизации будет сделать эту функцию берут 33 миллисекунд или меньше каждый раз, когда он работает. Эта функция многократно вызывает сама себя с помощью метода setTimeout() в JavaScript таймер, как показано ниже.

Второе правило: пока нет.

Это правило подчеркивает, что оптимизация всегда должно быть сделано в конце процесса развития, когда вы уже конкретизированы некоторые полный, рабочий код. Полиция оптимизация позволит нам идти на это, так как скрипт виджета-прекрасный пример полного, рабочая программа, готовая к процессу.

Третье правило: не еще, а профиль первого.

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

Я побежал виджет под профайлером в Firebug, и ниже представлен скриншот результатов.


Шаг 4: Установите Некоторые Показатели Производительности

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

Это не просто красивое лицо, что также обеспечивает некоторую статистику производительности в реальном времени на запущенной программы. Его на самом деле простой, голые кости профилировщика JavaScript. Это верно! Я слышал, что ты, как профилирование, так что я положил профилировщик в кино, так что вы можете профиль во время просмотра.

Этот график отслеживает время рендеринга, рассчитывается путем измерения, как долго каждый запуск функции main() в миллисекундах. Профайлер-это также удобный браузер рендеринга тест скорости. На данный момент, среднее время рендеринга в Firefox 55ms, 90МС в IE 9, 41ms в Chrome, 148ms в опере и 63ms в Safari. Красная горизонтальная линия-это скорость цели, которые мы ставим на 33ms, чтобы соответствовать частоту кадров видео файлов. Чуть ниже график, скорость последнего вызова main() дается в миллисекундах.

Профайлер-это также удобный браузер рендеринга тест скорости. На данный момент, среднее время рендеринга в Firefox 55ms, 90МС в IE 9, 41ms в Chrome, 148ms в опере и 63ms в Safari. Все браузеры были запущены на Windows XP, за исключением IE 9, который был представлен в Windows Vista для.

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

Последняя метрика браузера ФПС, который измеряет, сколько браузер перерисовывает текущее окно каждую секунду. Это доступно только при просмотре виджетов в Firefox, так как он зависит от того, в настоящее время функция доступна только в браузере под названием Окно.mozPaintCount., свойство JavaScript, который отслеживает, сколько раз в окне браузера была перекрашена так как веб-страница сначала загружается.

На перекрашивает, как правило, происходят, когда событие или действие, которое изменяет вид страницы происходит, например, когда вы прокрутите вниз страницу или наведите указатель мыши на ссылку. Это фактически реальная частота кадров в браузере, который определяется как занят текущей веб-страницы.

Чтобы оценить, какой эффект неоптимизированных анимации на mozPaintCount, я убрал тег Canvas и JavaScript, так как для отслеживания частоты кадров браузере при проигрывании только видео. Мои тесты были сделаны в консоли Firebug, с помощью функции ниже:

Результаты: частота кадров браузер был между 30 и 32 ФПС, когда видео играет, и упала до 0-1 ФПС, когда видео закончилось. Это означает, что Firefox был регулировать его частоту окно перерисовывается в соответствии игровое видео, закодированное при 30 кадров в секунду. Когда был выполнен тест с ООН-оптимизирован анимации и видео играющих вместе, он замедлился до 16fps, как браузер был сейчас изо всех сил, чтобы выполнить все JavaScript и еще перекрасить ее окно на время, что воспроизведение видео и анимации холст вяло.

Теперь мы начнем настройку нашей программы, и по мере этого мы будем отслеживать время Render Time, Canvas FPS и Browser FPS для измерения эффектов наших изменений.


Шаг 5: Используйте метод requestAnimationFrame()

Последние два вышеприведенных фрагментах кода JavaScript использовать функции setTimeout() и setInterval() функции таймера. Чтобы использовать эти функции, можно указать интервал времени в миллисекундах и функции обратного вызова, вы хотите выполнить истечении этого времени. Разница между двумя заключается в том, что метод setTimeout() будет вызывать функцию только один раз, а через setInterval() вызывает его повторно.

Хотя эти функции всегда были незаменимыми инструментами в комплекте на JavaScript аниматора, у них есть несколько недостатков:

Мы сейчас начать настройки нашей программы, и как мы это сделаем, мы будем отслеживать время рендеринга, холст ФПС и ФПС браузера, чтобы оценить эффект изменения.Во-первых, временной интервал установить не всегда надежны. Если программа все еще находится в середине выполнения чего-то еще, когда интервал истекает, функция обратного вызова будет выполняться позже, чем первоначально установленный, как только браузер больше не занят. В функции main (), мы установили интервал в 33 мс - но как профайлер показывает, что функция на самом деле называется Все 148 миллисекунд в опере.

Во-вторых, существует проблема с перекрашивает браузера. Если бы у нас была функция обратного вызова, которая генерируется 20 кадров анимации в секунду, в то время как браузер перекрасили своего окна только 12 раз в секунду, 8 вызовы этой функции будут потрачены впустую, так как пользователь никогда не получите, чтобы увидеть результаты.

Наконец, браузер не имеет возможности узнать, что вызываемая функция анимирует элементов в документе. Это означает, что если эти элементы прокрутки вне поля зрения, или пользователь нажимает на другую вкладку, обратный вызов будет по-прежнему вам неоднократно выполняться, тратить циклы процессора.

Используя метод requestAnimationFrame() решает большинство этих проблем, и ее можно использовать вместо функции таймера анимации в HTML5. Вместо указания временного интервала, метод requestAnimationFrame() синхронизирует вызовов функций в окне браузера перекрашивает. Это приводит к увеличению объема жидкости, последовательное анимация как нет кадров, и браузер может сделать дальнейшее внутренней оптимизации зная анимация в прогресс.

Чтобы заменить функции setTimeout() с помощью метода requestAnimationFrame в наш виджет, то сначала добавьте следующую строку в верхней части нашего скрипта:

Как спецификация является еще достаточно новой, в некоторых браузерах или в разных версиях одного браузера имеют собственных экспериментальных реализаций, эта линия гарантирует, что имя функции указывает на правильный метод, если он доступен, и падает обратно в setTimeout (), если не. Тогда в функции main (), мы меняем эту строку:

...чтобы:

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

Обратите внимание, что getStats() функция также использует метод setTimeout(), но мы оставим это в месте, поскольку эта функция не имеет ничего общего с анимацией сцены. метод requestAnimationFrame() был создан специально для анимации, так что если ваша функция обратного вызова не делаю анимации, вы можете использовать setTimeout() или setInterval().


Шаг 6: Используйте страницу API для видимости

В последнем шаге мы сделали метод requestAnimationFrame мощность полотно анимации, и теперь у нас новая проблема. Если у нас начать работать виджет, а затем свернуть окно браузера или перейти на новую вкладку, Окно которой виджета перекрасить дроссели вниз, чтобы сохранить власть. Это также замедляет холст анимации, поскольку он теперь синхронизирован с темпом перекрасить - что было бы прекрасно, если видео не продолжать играть до конца.

Нам нужен способ, чтобы определить, когда страница не просматривается, так что мы можете приостановить воспроизведение видео; это когда страница API видимости приходит на помощь.

API содержит набор свойств, функций и событий мы можем использовать, чтобы обнаружить, если веб-страница имеет вид или скрытая. Затем мы можем добавить код, который регулирует поведение нашей программы соответственно. Мы будем использовать этот API, чтобы приостановить воспроизведение видео виджета всякий раз, когда страница неактивна.

Мы начнем с добавления нового прослушивателя событий для нашего скрипта:

Далее идет функция обработчика событий:


Шаг 7: для нестандартной фигуры, нарисовать весь путь сразу

Дорожки используются, чтобы создать и нарисовать собственные формы и очертания на элементе элемент, который будет во все времена иметь один активный путь.

Путь содержит список суб-пути, и каждый суб-путь состоит из холста координатой точки связаны либо линией, либо кривой. Весь путь создания и рисования функций свойства объекта контекста холста, и могут быть классифицированы на две группы.

Есть подпути-функции, используемые для определения подпути и включают концы lineto(), quadraticCurveTo(), bezierCurveTo () и дуговой(). Тогда у нас есть инсульт() и заполнить(), путь/подпуть функции рисования. Используя инсульт() создает контур, а заливку() создает форму заполнять или цвет, градиент или узор.

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

Инсульт() метод в настоящее время называется в цикл, который определяет каждый подпуть:

Этот график можно сделать гораздо более эффективно, сначала нужно определить все подпути, то просто рисовал весь путь сразу, как показано ниже.


Шаг 8: использовать внеэкранный холст для построения сцены

Этот метод оптимизации относится к одним на предыдущем шаге, в том, что они оба основаны на том же принципе минимизации странице перекрашивает.

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

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

Чуть ниже код, который получает ссылку на виджета и его контекст, мы добавим пять новых линий, что создать внеэкранный холст объект DOM и сопоставить его размеры с оригинала, видны элемента .

Затем мы выполним поиск и замена во всех функциях рисования для всех ссылок на "mainCanvas" и изменить его на "osCanvas". Ссылки на "mainContext" будет заменено на "osContext". Все теперь будет обращено на новые закадровые холст, вместо оригинального элемента .

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


Шаг 9: Пути Кэша В Виде Растровых Изображений, Когда Это Возможно

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

Есть два способа сделать это.

Первый-путем создания внешнего файла изображения в формате JPG, GIF или PNG изображения, а затем загружать его динамически с помощью JavaScript и скопировав его на свой холст. Единственный недостаток этого метода-это дополнительные файлы, программу придется скачать из сети, но в зависимости от типа графика или что ваше приложение делает, это может оказаться хорошим решением. Виджет анимации использует этот метод, чтобы загрузить спиннинг лезвие графики, которые невозможно было бы воссоздать с помощью всего пути холсте функции рисования.

Второй способ подразумевает как раз после рисования графики на экране вместо загрузки внешнего изображения. Мы будем использовать этот метод для кэширования название виджета анимации. Сначала мы создаем переменную для ссылки на новое закадровое элемент canvas, который будет создан. Его значение по умолчанию-false, так что мы можем сказать, является ли или не кэшировать изображения был создан и сохраняется после того, как скрипт начинает выполняться:

Потом мы отредактируем drawTitle (функций) в первый проверить titleCache изображения холст был создан. Если это не так, он создает образ вне экрана и сохраняет ссылку на него в titleCache:


Шаг 10: очистить холст с метода clearrect()

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

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

В функции main (), мы изменим это:

...на это:


Шаг 11: Создание Слоев

Если вы работали с изображения или видео-редактирования программного обеспечения, как Gimp или Photoshop ранее, то вы уже знакомы с понятием "слои", где изображение состоит из укладки много изображений поверх друг друга, и каждый из них может быть выбран и изменен отдельно.

Наносится на холст сцены анимации, каждый слой будет отдельный элемент canvas, размещены на верхней части друг с другом с помощью CSS, чтобы создать иллюзию одного элемента. В качестве метода оптимизации, это работает лучше всего, когда есть четкое разграничение между переднего плана и фона элементов сцены, причем большая часть действий происходит на переднем плане. Фоновом режиме, затем можно нанести на холст элемент, который не сильно меняется между кадрами анимации, а на переднем плане еще более динамичный элемент canvas над ним. Таким образом, вся сцена не должна быть снова перерисовывается в каждом кадре анимации.

К сожалению, виджет анимации-это хороший пример сцены, где мы не можем с пользой применить этот метод, так как оба переднего плана и фона элементов сильно оживляются.


Шаг 12: обновить только изменения областей сцены анимации

Это еще один метод оптимизации, который в значительной степени зависит от состава анимацию сцены. Он может быть использован, когда сцена анимации концентрируется вокруг определенной прямоугольную область на холсте. Тогда мы могли бы ясно и просто перекроить перекроить этот регион.

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

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


Шаг 13: Минимизировать Субпиксельный Рендеринг

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

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

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

...переписана как:


Шаг 14: измерить результаты

Мы просмотрели немало холст методы оптимизации анимации, и его сейчас время, чтобы рассмотреть результаты.

Эта таблица показывает до и после среднего времени render и холст ФПС. Мы можем увидеть некоторые значительные улучшения во всех браузерах, но это только хром, что на самом деле приближается к достижению нашей первоначальной целью максимальной 33ms время рендеринга. Это означает, что еще многое предстоит сделать для достижения этой цели.

Мы могли бы продолжить, применяя более общие методы оптимизации JavaScript, а если и это не помогает, возможно, рассмотреть поубавить анимации, удалив некоторые навороты. Но мы не будем смотреть на другие методы сегодня, как основное внимание было уделено оптимизации для элемента анимация.

Холст API-это довольно таки новый и растет каждый день, поэтому продолжайте экспериментировать, тестирование, изучение и обмен. Спасибо за чтение учебника.

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.