I'm trying to get the FPS above 30 in Firefox. I'm really not sure what else I may do to improve it. Any suggestions?
Chrome and Opera hover around 60 fps, while FF is stuck between 10-20, and because of that it's causing lag issues on the rest of my page.
window.requestAnimFrame = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
function( callback ) {
window.setTimeout(callback, 1000 / 60);
};
})();
(function() {
particleCanvas();
con = particle.getContext('2d');
pxs = [];
for(var i = 0; i < 25; i++) {
pxs[i] = new Circle();
pxs[i].reset();
}
requestAnimFrame(paintParticles);
window.onresize = function(event) {
particleCanvas();
};
})();
function Circle() {
// settings
this.s = {
ttl:10000,
// speeds
xmax:4,
ymax:4,
// max size
size:1,
rt:4,
xdrift:60,
ydrift:60,
opacity: 0.3,
};
this.reset = function() {
// randomise positioning for each particle
this.x = particle.width * Math.random();
this.y = particle.height * Math.random();
// size
this.r = ((this.s.size-1)*Math.random()) + 1;
this.dx = (Math.random()*this.s.xmax) * (Math.random() < 0.5 ? -1 : 1);
this.dy = (Math.random()*this.s.ymax) * (Math.random() < 0.5 ? -1 : 1);
this.hl = this.s.ttl / 4 * (this.r/this.s.size);
this.rt = Math.random()*this.hl;
this.s.rt = Math.random() +1;
this.stop = Math.random();
this.s.xdrift *= Math.random() * (Math.random() < 0.5 ? -1 : 1);
this.s.ydrift *= Math.random() * (Math.random() < 0.5 ? -1 : 1);
};
this.fade = function() {
this.rt += 5 + this.s.rt;
};
this.draw = function() {
if(this.rt >= this.hl) this.reset();
var newo = 1 - (this.rt/this.hl);
con.globalAlpha = this.s.opacity;
con.beginPath();
con.arc(this.x,this.y,this.r,0,Math.PI*2,true);
con.closePath();
var cr = this.r*newo;
g = con.createRadialGradient(this.x, this.y, 0, this.x, this.y, (cr <= 0 ? 1 : 5));
g.addColorStop(0.0, 'rgba(255,255,255,' + newo + ')');
g.addColorStop(this.stop, 'rgba(255,255,255,' + 0.5 * newo + ')');
g.addColorStop(1.0, 'rgba(255,255,255, 0)');
con.fillStyle = g;
con.fill();
};
this.move = function() {
this.x += (this.rt/this.hl)*this.dx;
this.y += (this.rt/this.hl)*this.dy;
if(this.x > particle.width || this.x < 0) this.dx *= -1;
if(this.y > particle.height || this.y < 0) this.dy *= -1;
};
this.getX = function() { return this.x; };
this.getY = function() { return this.y; };
}
function particleCanvas() {
particle.width = document.querySelector('.start').offsetWidth / 2;
particle.height = document.querySelector('.start').offsetHeight / 2;
}
function paintParticles() {
requestAnimFrame(paintParticles);
con.clearRect ( 0 , 0 , particle.width, particle.height );
for(var i = 0; i < pxs.length; i++) {
pxs[i].fade();
pxs[i].move();
pxs[i].draw();
}
var thisFrameFPS = 1000 / ((now=new Date()) - lastUpdate);
fps += (thisFrameFPS - fps) / fpsFilter;
lastUpdate = now;
}
var fps = 0, now,
lastUpdate = (new Date())*1 - 1, fpsFilter = 50;
setInterval(function(){
document.querySelector('.fps').innerHTML = fps.toFixed(1) + ' fps';
}, 1000);
Your performance killer is creating a gradient for each particle during each animation frame.
You might swap the expensive gradient
for the relatively cheaper globalAlpha
.
Here's a refactoring that uses globalAlpha instead of gradient. I left it for you to tweak the globalAlpha to match your effect, but this refactoring is much faster on Firefox (59+ on my machine).
There are other optimizations possible in your code, but using gradients is the performance killer...
window.requestAnimFrame = (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function( callback ) { window.setTimeout(callback, 1000 / 60); }; })(); (function() { particleCanvas(); con = particle.getContext('2d'); pxs = []; for(var i = 0; i < 25; i++) { pxs[i] = new Circle(); pxs[i].reset(); } requestAnimFrame(paintParticles); window.onresize = function(event) { particleCanvas(); }; })(); function Circle() { // settings this.s = { ttl:10000, // speeds xmax:4, ymax:4, // max size size:1, rt:4, xdrift:60, ydrift:60, opacity: 0.7, }; this.reset = function() { // randomise positioning for each particle this.x = particle.width * Math.random(); this.y = particle.height * Math.random(); // size this.r = ((this.s.size-1)*Math.random()) + 1; this.dx = (Math.random()*this.s.xmax) * (Math.random() < 0.5 ? -1 : 1); this.dy = (Math.random()*this.s.ymax) * (Math.random() < 0.5 ? -1 : 1); this.hl = this.s.ttl / 4 * (this.r/this.s.size); this.rt = Math.random()*this.hl; this.s.rt = Math.random() +1; this.stop = Math.random(); this.s.xdrift *= Math.random() * (Math.random() < 0.5 ? -1 : 1); this.s.ydrift *= Math.random() * (Math.random() < 0.5 ? -1 : 1); this.s.opacity=0.70; }; this.fade = function() { this.rt += 5 + this.s.rt; this.s.opacity-=.005; }; this.draw = function() { if(this.rt >= this.hl) this.reset(); var newo = 1 - (this.rt/this.hl); con.globalAlpha = this.s.opacity; con.beginPath(); con.arc(this.x,this.y,this.r,0,Math.PI*2,true); con.closePath(); var cr = this.r*newo; con.fill(); }; this.move = function() { this.x += (this.rt/this.hl)*this.dx; this.y += (this.rt/this.hl)*this.dy; if(this.x > particle.width || this.x < 0) this.dx *= -1; if(this.y > particle.height || this.y < 0) this.dy *= -1; }; this.getX = function() { return this.x; }; this.getY = function() { return this.y; }; } function particleCanvas() { particle.width = document.querySelector('body').offsetWidth / 2; particle.height = document.querySelector('body').offsetHeight / 2; } function paintParticles() { requestAnimFrame(paintParticles); con.clearRect ( 0 , 0 , particle.width, particle.height ); con.fillStyle = 'white'; for(var i = 0; i < pxs.length; i++) { pxs[i].fade(); pxs[i].move(); pxs[i].draw(); } var thisFrameFPS = 1000 / ((now=new Date()) - lastUpdate); fps += (thisFrameFPS - fps) / fpsFilter; lastUpdate = now; } var fps = 0, now, lastUpdate = (new Date())*1 - 1, fpsFilter = 50; setInterval(function(){ document.querySelector('.fps').innerHTML = fps.toFixed(1) + ' fps'; }, 1000);
html, body {height:100%;width:100%;display:block;margin:0;padding:0;background:black} * {box-sizing:border-box} span { position:absolute; top:50px; left:50px; font-size:28px; color:white; font-family:mono; } canvas {width:100%;height:100%} </style>
<canvas id="particle"></canvas> <span class="fps"></span>
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.