Avery246813579 Avery246813579 - 2 months ago 7
Javascript Question

While drawing on canvas, there is a 1/10 chance that scrolling causes page to lag

I found that sometimes when I use my scroll wheel, my canvas will stop drawing. I tried to disable scrolling but the problem still occurs.

Here is an example of the lag: https://gyazo.com/8cc175a09ac3961ad59ebb46dca24d48

Code Below:

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
c.width = getWidth();
c.height = getHeight();

var iconNames = ['android', 'github', 'google-plus', 'instagram', 'linkedin', 'pinterest', 'reddit', 'skype', 'snapchat', 'soundcloud', 'tumblr', 'twitter', 'vimeo', 'youtube'];
var iconsDropped = 0, max = 7;
var drops = [];

for (var i = 0; i < iconNames.length; i++) {
var image = new Image();
image.src = "images/landing/" + iconNames[i] + ".png";
}

pickRandom();
function pickRandom() {
var wait = Math.floor(Math.random() * 2500);
setTimeout(pickRandom, wait);

if (iconNames.length < 1 || iconsDropped >= max) {
return;
}

var img = new Image();
var index = Math.floor(Math.random() * iconNames.length);
var name = iconNames[index];
iconNames.splice(index, 1);

img.onload = function () {
drops.push({
image: img,
width: Math.floor(Math.random() * getWidth()),
height: -50,
name: name,
speed: Math.random() + .5,
cycle: 0
});

iconsDropped++;
};

img.src = "images/landing/" + name + ".png";
}

function draw() {
c.width = getWidth();
c.height = getHeight() - c.offsetTop;
clearCanvas();

for (var i = 0; i < drops.length; i++) {
var drop = drops[i];
drop.height = drop.height + drop.speed;

if (drop.height > getHeight() - c.offsetTop) {
drop.cycle++;

if (drop.cycle == 3) {
var name = drop.name;
drops.splice(i, 1);
iconNames.push(name);
iconsDropped--;
i--;
continue;
} else {
drop.height = -50;
drop.width = Math.floor(Math.random() * getWidth());
}
}

ctx.drawImage(drop.image, drop.width, drop.height, 50, 50);
}

console.log("ASD")
}
setInterval(draw, 2);

function clearCanvas() {
ctx.clearRect(0, 0, c.width, c.height);
ctx.beginPath();
}

Answer

When doing custom animations, you should be using requestAnimationFrame instead of setInterval or setTimeout. This is so that the browser knows you are trying to do animations, and is able to cater to that with regards to things like scrolling, having the windows in the background, etc.

As per the docs:

You should call this method whenever you're ready to update your animation onscreen. This will request that your animation function be called before the browser performs the next repaint. The number of callbacks is usually 60 times per second, but will generally match the display refresh rate in most web browsers as per W3C recommendation. The callback rate may be reduced to a lower rate when running in background tabs or in hidden s in order to improve performance and battery life.