我已经创建了一个背景 Canvas ,可以绘制大约 300 个对象,现在当我移动鼠标时它会滞后很多。可能只是 Canvas 不是用来绘制 300 个对象的?
我已经做了一些关于优化的研究,比如只使用整数,这样抗锯齿就会更少。
<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>
初始化函数称为onresize
和onload
,我是否可以做任何更改来优化代码?或者我只是在挑战极限。
最佳答案
这里对 requestAnimationFrame 的工作方式有一点误解。
您不需要尝试以每秒 60 次(re:1000/60)的速度强制调用 requestAnimationFrame。这会自动发生。
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
您在这里真正做的是每隔 1000/60 调用一次超时,然后尝试调用 drawBackground
。由于超时不可靠,这会导致斜坡效应并导致您观察到的滞后问题。
从您的代码中删除 setTimeout,而是简单地使用
window.requestAnimationFrame(drawBackground);
除了超时使用之外,在运行 requestAnimationFrame 时多次调用 drawBackground
不是一个好主意 - 特别是考虑到它处理的数据不在函数范围内,这意味着它无论如何更新时都在使用星星数组。使用一个标志来确保动画尚未开始,以防止在初始化时多次调用它。
var animationRunning = false;
function initialize() {
//... existing code
if(!animationRunning){
drawBackground();
animationRunning = true;
}
}
关于Javascript 提高 Canvas 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49824045/