Javascript - Керування fps за допомогою переповнення стека requestAnimationFrame

Здається, requestAnimationFrame - це фактичний спосіб анімувати речі зараз. Здебільшого це спрацювало у мене досить добре, але зараз я намагаюся зробити кілька анімаційних полотен, і мені було цікаво: чи є спосіб переконатися, що він працює з певною частотою кадрів в секунду? Я розумію, що метою rAF є стабільно плавна анімація, і я міг би ризикнути зробити свою анімацію непосильною, але зараз, схоже, вона працює на різно різній швидкості досить довільно, і мені цікаво, чи є спосіб боротьби це якось.

Я б використовував setInterval, але я хочу оптимізації, яку пропонує rAF (особливо автоматично зупиняючись, коли вкладка знаходиться у фокусі).

Якщо хтось захоче поглянути на мій код, це в значній мірі:

Де Node.drawFlash () - це лише якийсь код, який визначає радіус на основі змінної лічильника, а потім малює коло.

10 відповідей 10

Як придушити requestAnimationFrame до певної частоти кадрів

Цей метод працює, перевіряючи час, що минув з моменту виконання останнього циклу кадру.

Код креслення виконується лише тоді, коли вказаний інтервал FPS минув.

Перша частина коду встановлює деякі змінні, що використовуються для обчислення минулого часу.

І цей код є фактичним циклом requestAnimationFrame, який звертається до вказаного вами FPS.

javascript

Оновлення 2016/6

Проблема зменшення частоти кадрів полягає в тому, що екран має постійну швидкість оновлення, як правило, 60 кадрів в секунду.

Якщо ми хочемо 24 кадрів в секунду, ми ніколи не отримаємо справжніх 24 кадрів в секунду на екрані, ми можемо визначити час як такий, але не показувати його, оскільки монітор може показувати синхронізовані кадри лише з частотою 15 кадрів в секунду, 30 кадрів в секунду або 60 кадрів в секунду (деякі монітори також 120 кадрів в секунду) ).

Однак для цілей хронометражу ми можемо підрахувати та оновити, коли це можливо.

Ви можете побудувати всю логіку для управління частотою кадрів, інкапсулюючи обчислення та зворотні виклики в об'єкт:

Потім додайте контролер та код конфігурації:

Використання

Це стає дуже просто - тепер все, що нам потрібно зробити, це створити екземпляр, встановивши функцію зворотного виклику та бажану частоту кадрів приблизно так:

Потім запустіть (що за бажанням може бути поведінкою за замовчуванням):

Ось і все, вся логіка обробляється внутрішньо.

Стара відповідь

Основною метою requestAnimationFrame є синхронізація оновлень із частотою оновлення монітора. Це вимагатиме анімації на FPS монітора або коефіцієнт його (тобто 60, 30, 15 FPS для типової частоти оновлення @ 60 Гц).

Якщо ви хочете отримати більш довільний кадр в секунду, тоді немає сенсу використовувати rAF, оскільки частота кадрів у будь-якому випадку ніколи не буде відповідати частоті оновлення монітора (просто кадр тут і там), що просто не може дати вам плавну анімацію (як і у всіх повторних синхронізаціях кадрів) ), і ви можете замість цього використовувати setTimeout або setInterval.

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

Причиною того, чому ми ставимо setTimeout спочатку (і чому деякі спочатку ставлять rAF, коли використовується полізаливка), є те, що це буде точніше, оскільки setTimeout поставить у чергу подію одразу при запуску циклу, так що незалежно від того, скільки часу залишиться код буде використовувати (за умови, що він не перевищує інтервал очікування) наступний виклик буде на інтервалі, який він представляє (для чистого rAF це не є важливим, оскільки rAF в будь-якому випадку намагатиметься перейти до наступного кадру).