I've created a background canvas that draw around 300 objects, Now it lags quite a bit when I move my mouse. It might just be that canvas isn't made to draw 300 objects?
I've done some research on optimizing such as only using integers so there will be less anti-aliasing.
<script>
var stars = [];
var starCount = 500;
var starColors = ["#125A89", "#409897", "#042B44", "#125987"];
//Setup canvas
var canvas = document.getElementById("background");
var ctx = canvas.getContext("2d");
//Initialize all the measurements
function initialize() {
var backgroundWidth = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
var backgroundHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
document.getElementById("myCanvas").setAttribute('width', backgroundWidth);
document.getElementById("myCanvas").setAttribute('height', backgroundHeight);
//Start the background and draw it
createStars(starCount);
drawBackground();
}
//Create the star objects in a array
function createStars(starCount) {
stars = [];
for (var i = 0; i < starCount; i ++) {
var star = {
size: getRandomInt(1, 3),
Yspeed: getRandomInt(4, 10),
Xpos: getRandomInt(0, canvas.width),
Ypos: getRandomInt(0, canvas.height),
color: starColors[getRandomInt(0, starColors.length)]
}
stars.push(star);
}
}
//Generate random number
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function drawBackground() {
//Clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
//Draw background
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "#000000";
ctx.fill();
//Draw al the stars from the array
for (var i = 0; i < stars.length; i ++) {
var star = stars[i];
ctx.beginPath();
ctx.rect(star.Xpos, star.Ypos, star.size, star.size);
if (ctx.fillStyle != star.color) ctx.fillStyle = star.color;
ctx.fill();
if (star.Ypos + star.size > canvas.height) star.Ypos = -star.size;
else star.Ypos += star.Yspeed;
}
//Call the next draw cycle
setTimeout(function() {
window.requestAnimationFrame(drawBackground);
}, 1000/60);
}
</script>
The initialize function is called onresize
and onload
, are there any changes I could make to optimize the code? Or am I just pushing the limit.
There is a slight misunderstanding here with the way that requestAnimationFrame works.
You don't need to attempt to force the call for requestAnimationFrame at 60 times per second (re: 1000/60). That happens automatically .
The window.requestAnimationFrame() method tells the browser that you wish to perform an animation and requests that the browser call a specified function to update an animation before the next repaint. The method takes a callback as an argument to be invoked before the 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.
- window.requestAnimationFrame() MDN
What you are really doing here is calling the timeout every 1000/60, which then attempts to call drawBackground
. Since timeouts are not reliable, this results in a ramping effect and causes the lag issues you are observing.
Remove the setTimeout from your code, and instead simply use
window.requestAnimationFrame(drawBackground);
In addition to the timeOut use, calling drawBackground
multiple times when it is running requestAnimationFrame is not a good idea - especially given that the data it working on is not scoped to the function, meaning that it is using the stars array when it is updated anyway. Use a flag to ensure that the animation hasn't already started to prevent calling this multiple times from initialize.
var animationRunning = false;
function initialize() {
//... existing code
if(!animationRunning){
drawBackground();
animationRunning = true;
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.