Рисовать изображения на холсте с разной скоростью

Имея два разных изображения (скажем, image A и image B), предположим, я хочу нарисовать image A на холсте со скоростью около 60 кадров в секунду, а я хочу нарисовать image B со скоростью около 30 кадров в секунду.

У меня вопрос: как лучше всего это сделать с помощью requestAnimationFrame? Должен ли я создать 2 холста?


person Safirah    schedule 21.06.2017    source источник
comment
обратный вызов requestAnimationFrame получает отметку времени в качестве первого аргумента. Используйте эту метку времени для вычисления времени, прошедшего между последним и текущим выполнением обратного вызова, и рисуйте в соответствии с этим.   -  person le_m    schedule 21.06.2017
comment
@le_m, но для этого мне нужно использовать 2 холста, верно?   -  person Safirah    schedule 21.06.2017
comment
Вам просто нужно отслеживать два раза. Вам не нужен дополнительный холст.   -  person le_m    schedule 21.06.2017


Ответы (2)


Обратный вызов requestAnimationFrame получает отметку времени в качестве первого аргумента. Используйте эту метку времени для вычисления времени, прошедшего между последним и текущим выполнением обратного вызова, и рисуйте в соответствии с этим.

Вот простой пример, демонстрирующий вышеуказанный принцип:

let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');

let last100 = 0;
let last500 = 0;

function frame(time) {
  ctx.fillStyle = 'rgb(' + Math.random() * 255 + ', 0, 0)';
  
  // 10 frames per second (1000/10 = 100):
  if (time > last100 + 100) {
    ctx.fillRect(0, 0, 100, 100);
    last100 = time;
  }
  
  // 2 frames per second (1000/2 = 500):
  if (time > last500 + 500) {
    ctx.fillRect(200, 0, 100, 100);
    last500 = time;
  }
  requestAnimationFrame(frame);
}

requestAnimationFrame(frame);
<canvas id="canvas"></canvas>

person le_m    schedule 21.06.2017

Вы также можете использовать 2 холста, но заставить их действовать как слои, то есть «складывать их», используя абсолютное позиционирование.

Здесь есть полезная статья, написанная Джеймс Литтен

Я запустил скрипку; потребуется небольшая настройка в соответствии с вашими потребностями (код такой же, как фрагмент)

var layer1 = document.getElementById("layer1");
var layer2 = document.getElementById("layer2");
var ctx1 = layer1.getContext("2d");
var ctx2 = layer2.getContext("2d");

var img1 = loadImage('http://www.rachelgallen.com/images/purpleflowers.jpg', main);
var img2 = loadImage('http://www.rachelgallen.com/images/yellowflowers.jpg', main);

var imagesLoaded = 0;

function main() {
  imagesLoaded += 1;

  if (imagesLoaded == 2) {
    // set alpha for individual images as desired
    ctx1.globalAlpha = 0.8;
    ctx2.globalAlpha = 0.5;
     drawAll();
  }
}

function draw1() {
  frameRate = 30;
  ctx1.clearRect(0, 0, 250, 150);
  ctx1.beginPath();
  ctx1.rect(0, 0, 250, 150);
  ctx1.drawImage(img1, 0, 0); //draw 1st image
  ctx1.closePath();
}

function draw2() {
  frameRate = 60;
  ctx2.clearRect(0, 0, 250, 150);
  ctx2.beginPath();
  ctx2.rect(0, 0, 250, 150);
  ctx2.drawImage(img2, 0, 0); //draw 2nd image
  ctx2.closePath();
}

function drawAll() {
  draw1();
  draw2();
}

function loadImage(src, onload) {
  var img = new Image();

  img.onload = onload;
  img.src = src;

  return img;
}
#layer1,
#layer2 {
  position: absolute;
  top: 0;
  left: 0;
}
<canvas id="layer1">

</canvas>
<canvas id="layer2">

</canvas>

person Rachel Gallen    schedule 21.06.2017
comment
Джеймс использует setInterval при рисовании своих слоев. В приведенном выше коде он не используется. - person Rachel Gallen; 21.06.2017
comment
Да, мой план состоял в том, чтобы наложить два холста друг на друга, но небольшая настройка кода @le_m может помочь в этом. - person Safirah; 21.06.2017