Pull to refresh

Продвинутые анимации с requestAnimationFrame

JavaScript *
Translation
Original author: Paul Irish
Если вы никогда не писали код для выполнения анимаций, то вы можете дальше не читать :)

Что такое requestAnimationFrame?


Во всех ваших функциях анимаций вы используете повторяющийся таймер для применения изменений каждый несколько миллисекунд. Хорошие новости: производители браузеров решили «почему бы нам не дать вам API для этого потому, что мы, возможно, сможем оптимизировать некоторые моменты для вас». Итак, это основное API для создания анимаций на основе изменения DOM стилей, перерисовки canvas или WebGL

Зачем я должен это использовать?


Браузеры могут оптимизировать анимации идущие одновременно, уменьшив число reflow и repaint до одного, что в свою очередь приведет к повышению точности анимации. Например анимации на JavaScript синхронизированные с CSS transitions или SVG SMIL. Плюс ко всему если выполняется анимация в табе, который невидим, браузеры не будут продолжать перерисовку, что приведет к меньшему использованию CPU, GPU, памяти и как следствие снизит расход батареи в мобильных устройствах.

Пример использования


    // Если ничего нет - возвращаем обычный таймер
    window.requestAnimFrame = (function(){
      return  window.requestAnimationFrame       || 
              window.webkitRequestAnimationFrame || 
              window.mozRequestAnimationFrame    || 
              window.oRequestAnimationFrame      || 
              window.msRequestAnimationFrame     || 
              function(/* function */ callback, /* DOMElement */ element){
                window.setTimeout(callback, 1000 / 60);
              };
    })();
 
 
    // Использование: 
 
    (function animloop(){
      render();
      requestAnimFrame(animloop, element);
    })();

Замечание: я использую requestAnimFrame потому что спецификация все ещё в процессе разработки и поэтому я не хочу заранее объявлять глобальный requestAnimationFrame (применять polyfill)

Посмотреть в действии можно тут: jsfiddle.net/paul/XQpzU

requestAnimationFrame API


window.requestAnimationFrame(function(/* time */ time){
	// time ~= +new Date
}, /* связанный элемент */ elem);

В callback передается текущее время, оно в любом случае будет вам необходимо. Вторым параметром передается связанный с текущей анимацией элемент (для оптимизации). Для canvas и WebGL это будет элемент <canvas>. Для прочих анимаций вы можете ничего не передавать либо определить для повышения производительности.

Уже можно использовать?


Сейчас Webkit (Nightly Safari и Chrome Dev Channel) и Mozilla (FF4) немного отличаются. Mozilla имеет баг, который лимитирует количество кадров анимации (порядка 30) На самом деле, «оно лимитируется 1000/(16 + N) fps, где N количество миллисекунд необходимое для выполнения функции анимации. Если функция занимает 1 секунду, то количество кадров будет менее 1 в секунду. Если функция анимации занимает 1 мсек, то количество кадров будет около 60» Это будет исправлено на следующем релизе FF, но после FF4. Также Chrome 10 не имеет time параметра (добавлено в m11), FF сейчас игнорирует аргумент elem.

Пишите отзывы!


Если вы работаете с анимациями, то разработчики WebKit и Gecko будут рады услышать ваши отзывы и пожелания. Посмотрите черновик спецификации requestAnimationFrame Сейчас он действует как setTimeout; стоит ли заменить на setInterval? Имеет ли это API недостатки при анимации нескольких объектов адновременно? Работает ли оптимизация elem? Покрывает ли это API все потребности анимации?

Другие источники

  1. Draft spec (authored by heycam and jamesr)
  2. Chromium design doc
  3. A basic example
  4. A more comprehensive example with some available config
  5. MDC docs on mozRequestAnimationFrame
  6. Библиотеки использующие таймеры анимаций yui anim loop, three.js, limejs, ticket for jQuery's implementation
  7. Demo by Louis-Rémi Babé при переключении табов посмотрите на загрузку процессора
  8. Nokarma's coverage of requestAnimationFrame
  9. Mozilla's Robert O'Callhan early post on rAF
Tags:
Hubs:
Total votes 27: ↑25 and ↓2 +23
Views 65K
Comments Comments 36