Время вызова RequestAnimationFrame изменяется в зависимости от размера моего холста - PullRequest
3 голосов
/ 25 марта 2012

В моем приложении есть холст, размер которого (CSS, а не html) обновляется в зависимости от размера окна.

У меня есть основной геймплейный цикл, который выглядит следующим образом:

run = function(){

    console.log(timerDiff(frameTime));

    game.inputManage();
    game.logics();
    game.graphics.animate();
    game.graphics.render();

    frameTime = timerInit();

    requestAnimFrame(run);

}

Моя функция requestAnimFrame от Paul Irish:

window.requestAnimFrame = (function(){
  return  window.requestAnimationFrame       || 
          window.webkitRequestAnimationFrame || 
          window.mozRequestAnimationFrame    || 
          window.oRequestAnimationFrame      || 
          window.msRequestAnimationFrame     || 
          function( callback ){
            window.setTimeout(callback, 1000 / 60);
          };
})();

Таким образом, в основном проблема заключается в том, что таймер, который я регистрирую, который измеряет время между вызовом requestAnimFrame и эффективным вызовом функции, полностью изменяется. Если мой браузер работает в полноэкранном режиме, я получаю 50/60 мс, а если у меня маленькое окно, я могу получить что-то вроде 10 мс.

Поскольку предполагается, что вызов requestAnimFrame должен постоянно вызывать функцию с ритмом 60fps (что составляет около 30 мс, я думаю), у меня не должно быть такого результата, поскольку между созданием таймера и его таймером в принципе ничего не происходит. проверка, кроме запроса AnimFrame

У меня также есть несколько повторяющихся микрозамерзаний (менее секунды), которые происходят каждые 2/3 секунды. Но таймер не обнаруживает изменений во времени (как, например, даже счетчик времени в javascript заблокирован)

Мои функции таймеров такие, но здесь это не имеет значения

timerInit = function()
{
    return new Date();
}

timerDiff = function(datePrev)
{
    return new Date().getTime() - datePrev.getTime();
}

Ответы [ 2 ]

7 голосов
/ 25 марта 2012

Что ж, стандарт в основном гласит, что requestAnimationFrame будет "делать все возможное", чтобы работать с "постоянной" частотой кадров. Это не гарантирует 60 кадров в секунду; он просто заявляет, что оживит так быстро, как только сможет.

К сожалению, мой опыт с ним был таким же тусклым, как и ваш. Я закончил тем, что вернулся к setTimeout. Это происходит примерно с той же скоростью, и графические обновления точны и не пропускают такт, как это было с requestAnimationFrame. Конечно, это не было 60fps, но, по крайней мере, вы могли бы сказать, что происходит.

Я уверен, что производительность улучшится только тогда, когда разработчики браузеров оптимизируют новую функцию, но пока вернемся к timeouts.

Редактировать: Я хотел бы напомнить людям, что на это ответили год назад, и времена изменились:)

4 голосов
/ 31 июля 2012

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

Конечно, это так, поэтому вам нужно измерить его, и НА ОСНОВЕ ЭТОГО РАЗЛИЧНОГО ВРЕМЕНИ вы рассчитываете следующий кадр.

Предположим, вы хотите анимировать свойство 'left' css для div с 0px до 120px за 1 секунду с 60 кадрами в секунду.

  • с использованием setTimeout , поскольку ВЫ устанавливаете количество кадров, вы знаете, насколько вы должны увеличивать свойство left: 120px / 60frames = 2px / frame

  • используя requestAnimationFrame , у вас нет представления, когда произойдет следующий кадр, пока он не произойдет; затем вы измеряете разницу во времени между этим и предыдущим кадром и вычисляете значение, которое вы должны увеличить с помощью css 'left value'; если кадр происходит через 500 мс, расстояние приращения = (120 пикселей * 500 мс) / 1000 мс = 60 пикселей; Идея состоит в том, что в начале анимации вы не можете иметь фиксированное, предопределенное значение, которое будет увеличиваться в каждом кадре, вам нужно рассчитать его динамически на основе разницы во времени

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

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

...