Блокировка FPS для HTML Canvas/Javascript

Я пытался сделать покадровую анимацию с помощью таблицы спрайтов, которую я сделал на веб-сайте HTML, и я не мог понять, как заблокировать fps для анимации. Проблема в том, что это всегда происходит с молниеносной скоростью, и я хочу иметь возможность заблокировать его со скоростью ~ 10-15 кадров в секунду. Я пробовал использовать метод Date.now() и метод setInterval, но, похоже, он не работает на данный момент.

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

function animateCharacter() {
    var canvas = document.getElementById("portrait");
    var context = canvas.getContext("2d");
    var character = new Image();
    character.src = "/assets/spritesheet.jpg";
    animate();
    function animate() {

        context.drawImage(character, shift, 0, width, height, 300, 0, width / 2, height / 2);

        if (currentFrame == totalFrames) {
            shift = 0;
            currentFrame = 0;
        }
        requestAnimationFrame(animate);

}

person Brain Meme    schedule 13.12.2017    source источник


Ответы (2)


Вы можете попробовать setTimeout

 function animate(){
// do your animation
//     workout your frame rate
  setTimeout(animate, 500);
 };
 animate();
person Fan Cheung    schedule 13.12.2017

Есть несколько способов решить эту проблему, но общая идея состоит в том, чтобы проверить HighResTimeStamp, который вы получили в обратном вызове rAF, и обновить свои значения в соответствии с ним.

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

const ctx = c.getContext('2d');

// we need to know when the last frame did trigger
let lastTick = performance.now();
function anim(time){
  const time_spent = time - lastTick,
    passed_frames = time_spent / (1000 / FPS.value);
  if(passed_frames >= 1){
    update(passed_frames);
    lastTick = time;
    draw();
  }
  requestAnimationFrame(anim);
}

let x = 0;
const speed = 5;
function update(time_delta){
  x = (x + (speed * time_delta)) % (c.width - 10);
}
function draw(){
  ctx.clearRect(0,0,c.width,c.height);
  ctx.fillRect(x, 50, 20, 20);
}

anim(performance.now());
<label>FPS: 1<input id="FPS" type="range" min="1" max="120">120</label><br>
<canvas id="c"></canvas>

Обратите внимание, что это только одна из многих возможных реализаций, мы также могли бы округлить это значение time_delta и/или даже выполнить update в цикле for, или...

person Kaiido    schedule 13.12.2017