如何在addEventListener('click')上将SetInterval中的函数相乘;

时间:2016-01-16 19:24:20

标签: javascript

所以我制作了这段代码(在教程的帮助下),我希望无论在哪里点击都能创建效果。

代码完成它所拥有的功能,但每次我再次点击并调用'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);

};

1 个答案:

答案 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);

};