Рендерит холст быстрее 60 раз в секунду? - PullRequest
0 голосов
/ 31 мая 2018

Мой код JS:

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");

var mouse = {x:0,y:0}

const times = [];
let fps;

function refreshLoop() {
  window.requestAnimationFrame(() => {
    const now = performance.now();
    while (times.length > 0 && times[0] <= now - 1000) {
      times.shift();
    }
    times.push(now);
    fps = times.length;
    refreshLoop();
  });
}

refreshLoop();

function draw() {
  ctx.fillStyle = "black"
  ctx.fillRect(0, 0, c.width, c.height);
  ctx.strokeStyle = "white"
  ctx.beginPath();
  var e = window.event;
  ctx.arc(mouse.x, mouse.y, 40, 0, 2*Math.PI);
  ctx.stroke();
  ctx.font = "30px Comic Sans MS";
  ctx.fillStyle = "red";
  ctx.textAlign = "center";
  ctx.fillText(fps, c.width/2, c.height/2); 
}

setInterval(draw, 0);

document.addEventListener('mousemove', function(event){
  mouse = { x: event.clientX, y: event.clientY }
})

Мой HTML - это просто объявление canvas.

Насколько я понимаю, setinterval (x, 0) должен работать максимально быстро, но никогда не превышать 60 кадров в секунду.Я пытаюсь набрать 240+ кадров в секунду, чтобы уменьшить задержку ввода.

1 Ответ

0 голосов
/ 31 мая 2018

Во-первых, никогда используйте setInterval(fn, lessThan10).Существует большая вероятность, что для выполнения fn потребуется больше времени, и вам может понадобиться сложить много вызовов fn без какого-либо интервала, что может * привести к тому же результату, что и известный while(true) Браузер браузера® .

* Хорошо, в правильных реализациях этого не должно происходить, но вы знаете ...


Теперь к вашему вопросу ...

Ваш код довольно некорректен.

На самом деле вы одновременно запускаете два разных цикла, которые не будут вызываться с одинаковым интервалом.

  • Вы проверяете fps в цикле requestAnimationFrame , который будет установлен на той же частоте, что и скорость рисования вашего браузера (обычно 60 * fps *)).
  • Вы рисуете в setInterval(fn, 0) Ваши два цикла не связаны и, следовательно, то, что вы измеряете в первом, не является скоростью, с которой ваш draw называется.

Это немного похоже на то, что вы сделали

setInterval(checkRate, 16.6);
setInterval(thefuncIWantToMeasure, 0);

Очевидно, ваш checkRate не будет правильно измерять thefuncIWantToMeasure

Так что просто чтобы показать, что цикл setTimeout(fn, 0)будет стрелять с большей скоростью:

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");

var mouse = {
  x: 0,
  y: 0
}

const times = [];
let fps;
draw();

function draw() {
  const now = performance.now();
  while (times.length > 0 && times[0] <= now - 1000) {
    times.shift();
  }
  times.push(now);
  fps = times.length;

  ctx.fillStyle = "black"
  ctx.fillRect(0, 0, c.width, c.height);
  ctx.strokeStyle = "white"
  ctx.beginPath();
  ctx.arc(mouse.x, mouse.y, 40, 0, 2 * Math.PI);
  ctx.stroke();
  ctx.font = "30px Comic Sans MS";
  ctx.fillStyle = "red";
  ctx.textAlign = "center";
  ctx.fillText(fps, c.width / 2, c.height / 2);
  setTimeout(draw, 0);
}
<canvas id="myCanvas"></canvas>

Теперь, даже если вложенный цикл setTimeout лучше, чем setInterval, вы выполняете визуальную анимацию.

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

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

Теперь, чтобы решить реальную проблему, которая заключается не в рендеринге с более высокой скоростью, а в обработке входных данных пользователя с такой скоростью, тогда решение состоит в том, чтобы разделить ваш код.

  • Держите свою часть чертежа привязанной к циклу requestAniamtionFrame, не нужно ускоряться.
  • Обновите значения вашего объекта, которые должны синхронно реагировать на жест пользователя из ввода пользователя. Однако остерегайтесь жестов некоторых пользователей, которые на самом деле стреляют с очень высокой скоростью (например, WheelEvent или событие изменения размера окна).Как правило, вам не нужно получать все значения таких событий, поэтому вы можете вместо этого связать их в дросселях rAF.
  • Если вам нужно обнаружить столкновения с движущимися объектами, затем выполнитеМатематика, которая обновляет движущиеся объекты изнутри жеста пользователя, , но не рисует его на экране .
...