所以我用canvas和javascript(一些jQuery)创建了一个简单的粒子系统,但我似乎无法让它在旧计算机上以超过8fps的速度运行,这就是代码:
var starList = [];
function Star(){
this.x = getRandomInt(0, canvas.width);
this.y = getRandomInt(0, canvas.height);
this.vx = getRandomInt(2,5);
this.size = this.vx/5;
this.opacity = getRandomInt(0, 5000) / 10000;
this.color = getRandomFromArray(["239, 207, 174", "162, 184, 229", "255, 255, 255"]);
this.draw = function(){
ctx.fillStyle = "rgba("+this.color+","+this.opacity+")";
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
},
this.move = function(){
this.x = this.x - this.vx;
if(this.x < 0) {
this.x = canvas.width;
this.opacity = getRandomInt(0, 5000) / 10000;
this.color = getRandomFromArray(["239, 207, 174", "162, 184, 229", "255, 255, 255"]);
this.y = getRandomInt(0, canvas.height);
this.size = this.vx/5;
this.vx = getRandomInt(2,5);
}
}
}
var canvas, ctx;
function setCanvas(){
canvas = $('canvas')[0];
ctx = canvas.getContext("2d");
canvas.width = $(window).width()/5;
canvas.height = $(window).height()/5;
}
setCanvas();
function generateStars(){
for(var i = 0; i < 5000; i++){
var star = new Star();
starList.push(star);
}
for(var i = 0; i < starList.length; i++) {
star = starList[i];
star.draw();
}
}
generateStars();
function loop() {
window.requestAnimationFrame(loop);
//clear canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
//draw and move stars
for(var i = 0; i < starList.length; i++) {
star = starList[i];
star.draw();
star.move();
}
}
我假设使用粒子(星星)的对象并循环遍历5000个索引的对象数组,并且在处理器/ gpu上执行这两个函数很难但是如何优化这些代码呢?
我已经看到其他人避免在构造函数上使用函数,并在粒子循环遍历时移动和绘制粒子。这会让它更快吗?
编辑:忽略getRandomInt和类似的函数,它们是我用来生成随机内容的简单函数。
答案 0 :(得分:2)
代码中最慢的部分是路径绘制命令:
ctx.fillStyle = "rgba("+this.color+","+this.opacity+")";
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2, true);
ctx.closePath();
ctx.fill();
Canvas绘制速度非常快,但5000张绘图需要一些时间。
<强>相反... 强>
创建一个spritesheet,其中包含您要显示的所有星形变体。
将spriteesheet中的像素复制到显示画布比执行绘图命令快得多。对于绘制弧线尤其如此,其中必须围绕圆周计算许多点。
重要!
限制星星变化 - 观众不会注意到你的星星不是无限随机的。
然后使用drawimage
的剪切版本快速从spritesheet中绘制每个所需的星形精灵:
// set the global alpha
ctx.globalAlpha = getRandomInt(0, 5000) / 10000;
// cut the desired star-sprite from the spritesheet
// and draw it on the visible canvas
ctx.drawImage( spritesheet, // take from the spritesheet
this.sheetX, this.sheetY, this.width, this.height, // at this sprite's x,y
this.x, this.y, this.width, this.height) // and draw sprite to canvas
spritesheet
您可以使用第二个内存中的画布作为spritesheet,并在应用首次启动时在客户端创建星形精灵。 drawImage
命令将接受您的第二个内存中画布作为图像源(!)。
var spritesheet=document.createElement('canvas');
var spriteContext=spriteSheet.getContext('2d');
...
// draw every variation of your stars on the spritesheet canvas
...