所以我制作了这段代码(在教程的帮助下),我希望无论在哪里点击都能创建效果。
代码完成它所拥有的功能,但每次我再次点击并调用'drawParticle'功能时,过程加速并显示更少的粒子。 我认为这是因为我在JavaScript是单线程时同时调用多个setIntervals。但我该如何解决呢?
var canvas,
c,
particles,
particleIndex,
particleNum,
w,
h;
window.onload =function(){
canvas = document.createElement("canvas");
c = canvas.getContext("2d");
particles = {};
particleIndex = 0;
particleNum = 3;
w = window.innerWidth;
h = window.innerHeight;
canvas.width = w;
canvas.height = h;
document.body.appendChild(canvas);
c.fillStyle ="black";
c.fillRect(0,0,canvas.width,canvas.height);
canvas.addEventListener('click', drawParticle, false);
};
function drawParticle(e){
function Particle(){
this.x = e.clientX;
this.y = e.clientY;
this.vx = Math.random() * 10 - 5;
this.vy = Math.random() * 10 - 5;
this.gravity = 0.2;
particleIndex++;
particles[particleIndex] = this;
this.id = particleIndex;
this.life = 0;
this.maxLife = Math.random() * 30 + 50;
this.color = "rgb("+parseInt(Math.random()*255,10)+",0,0)";
}
Particle.prototype.draw = function(){
this.x += this.vx;
this.y += this.vy;
if(Math.random() < 0.1 ){
this.vx = Math.random() * 10 - 5;
this.vy = Math.random() * 10 - 5;
}
//this.vy += this.gravity;
this.life++;
if(this.life >= this.maxLife){
delete particles[this.id];
}
c.fillStyle = this.color;
c.fillRect(this.x,this.y,10,10);
};
interval = setInterval(function(){
//c.globalCompositeOperation ="source-over";
c.fillStyle ="rgba(0,0,0,0.3)";
c.fillRect(0,0,canvas.width,canvas.height);
for (var i = 0; i < particleNum; i++){
new Particle();
}
//c.globalCompositeOperation ="lighter";
for (var i in particles){
particles[i].draw();
}
},30);
};
答案 0 :(得分:0)
我认为你对这个间隔是正确的。我不确定这是否是您想要的反应,但如果您在重绘之前清除间隔,事情就不会加快。尝试类似:
var interval = null;
function drawParticle(e){
if (interval) {
clearInterval(interval)
}
function Particle(){
...
这里有一个codepen http://codepen.io/bunnymatic/pen/BjwVBM
更新:
我已经更改了代码笔以包含下面包含的新代码。主要的变化是创建一个Particles
对象,该对象将为每次单击绘制一组粒子。通过移动这些粒子集合,他们的particleIndex
似乎已经解决了这个问题。我怀疑将每个元素添加到全局particles
列表中有些奇怪。现在,Particles
实例仅管理与该组关联的粒子。
我也拿出了particleId
因为它似乎没必要,但如果它对这段代码的其他内容有用,你可能需要把它放回去。
这是我更新的代码:
var canvas,
c,
particleNum,
w,
h;
window.onload =function(){
canvas = document.createElement("canvas");
c = canvas.getContext("2d");
particleNum = 3;
w = window.innerWidth;
h = window.innerHeight;
canvas.width = w;
canvas.height = h;
document.body.appendChild(canvas);
c.fillStyle ="black";
c.fillRect(0,0,canvas.width,canvas.height);
canvas.addEventListener('click', drawParticles, false);
};
function Particles() {
this.particles = {};
this.particleIndex = 0;
}
Particles.prototype.addParticle = function(particle) {
this.particles[++this.particleIndex] = particle;
}
Particles.prototype.killDeadParticles = function() {
for (var i in this.particles) {
var particle = this.particles[i];
if (particle.isDead()) {
delete this.particles[i]
}
}
}
Particles.prototype.draw = function() {
// draw particles
for (var i in this.particles){
this.particles[i].draw();
}
this.killDeadParticles();
}
function Particle(e){
this.x = e.clientX;
this.y = e.clientY;
this.vx = Math.random() * 10 - 5;
this.vy = Math.random() * 10 - 5;
this.gravity = 0.2;
this.life = 0;
this.maxLife = Math.random() * 30 + 50;
this.color = "rgb("+parseInt(Math.random()*255,10)+",0,0)";
// console.log('new particle', particleIndex);
}
Particle.prototype.isDead = function() {
return (this.life >= this.maxLife);
}
Particle.prototype.draw = function(){
this.x += this.vx;
this.y += this.vy;
if(Math.random() < 0.1 ){
this.vx = Math.random() * 10 - 5;
this.vy = Math.random() * 10 - 5;
}
//this.vy += this.gravity;
this.life++;
c.fillStyle = this.color;
c.fillRect(this.x,this.y,10,10);
};
function drawParticles(e){
var particles = new Particles(e);
setInterval(function(){
//c.globalCompositeOperation ="source-over";
c.fillStyle ="rgba(0,0,0,0.3)";
c.fillRect(0,0,canvas.width,canvas.height);
for (var i = 0; i < particleNum; i++){
var particle = new Particle(e);
particles.addParticle(particle);
}
//c.globalCompositeOperation ="lighter";
particles.draw();
},30);
};