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

HTML5 Полотно оптимізація: практичний приклад

by
Read Time:32 minsLanguages:

Ukrainian (українська мова) translation by Tanya Ira (you can also view the original English article)

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

 Цей підручник починається і закінчується з тим, що віджет HTML5 анімації, які ви бачите нижче:

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

 Вихідний файл містить HTML і JavaScript від кожного кроку в підручник, так що ви можете слідувати поряд з будь-якої точки.

 Давайте зробимо перший крок.


Крок 1: грати в кіно трейлер 

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

 В теге для завантаження і відтворення відео файлів Синтел, в той час як <полотно> генерує свою послідовність анімації зйомки ігрового відео і змішування його з тексту та іншої графіки. При натисканні на відтворення відео, полотно оживає з темним фоном, що велика чорно-біла копія ігрового відео.  Менше, кольоровий екран-кадри відео копіюються на місце, і вона промайне, як частина плівки малюнку.

 У лівому верхньому куті, заголовок і кілька рядків тексту, які з'являються і зникають, як відтворюється анімація.  Швидкість роботи скрипта і супутні показники включені як частина анімації, невеликий чорний ящик в лівому нижньому куті графіка і яскравий текст. Ми будемо дивитися на цей конкретний пункт більш докладно пізніше.

 Нарешті, є великий обертається лопаті, яка літає по сцені на початку анімації, графіки яких завантажується з зовнішнього файлу зображення у форматі 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() у мілісекундах.  Оскільки це функція, яка розмальовує кожен кадр анімації, це ефективно частоту кадрів анімації. Кожна вертикальна синя лінія на діаграмі показано час, що витрачається на один кадр.  Червона горизонтальна лінія-це швидкість цілі, які ми ставимо на 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 і ще перефарбувати її вікно на час, що відтворення відео і анімації полотно мляво.

 Ми зараз почати налаштування нашої програми, і як ми це зробимо, ми будемо відстежувати час рендеринга, полотно ФПС і ФПС браузера, щоб оцінити ефект зміни.


Крок 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
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.