My JS code:
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 }
})
My HTML is just the canvas declaration.
To my understanding, setinterval(x, 0) is supposed to run as fast as possible but it's never exceeding 60fps. I'm trying to hit 240+ fps to reduce input lag.
First, never use setInterval(fn, lessThan10)
. There is a great possibility that fn
will take more than this time to execute, and you may end up stacking a lot of fn
calls with no interval at all, which can result* in the same as the well known while(true)
browser crasher®.
*Ok, in correct implementations, that shouldn't happen, but you know...
Now, to your question...
Your code is quite flawn.
You are actually running two different loops concurrently, which will not be called at the same interval.
setInterval(fn, 0)
Your two loops are not linked and thus, what you are measuring in the first one is not the rate at which your draw
is called.It's a bit like if you did
setInterval(checkRate, 16.6);
setInterval(thefuncIWantToMeasure, 0);
Obviously, your checkRate
will not measure thefuncIWantToMeasure
correctly
So just to show that a setTimeout(fn, 0)
loop will fire at higher rate:
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>
Now, even if a nested setTimeout
loop is better than setInterval
, what you are doing is a visual animation.
It makes no sense to draw this visual animation faster than the browser's painting rate, because what you will have drawn on this canvas won't be painted to screen.
And as said previously, that's exactly the rate at which an requestAnimationFrame
loop will fire. So use this method for all your visual animations (At least if it has to be painted to screen, for some rare case there are other methods I could link you to in comments if needed).
Now to solve your actual problem, which is not to render at higher rate, but to handle user's inputs at such rate, then the solution is to split your code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With