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

How to multiply a function in a SetInterval on a addEventListener('click');

本文关键字:SetInterval 函数 上的 click addEventListener      更新时间:2023-09-26

所以我制作了这段代码(在教程的帮助下),我想在我点击的任何地方创建效果。

代码做了它必须做的事情,但是每次我再次单击并调用"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);
};

我认为您对间隔的看法是正确的。 我不确定这是否是您想要的反应,但是如果您在重绘之前清除间隔,事情就不会加快。 尝试类似操作:

var interval = null;
function drawParticle(e){
  if (interval) { 
    clearInterval(interval)
  }
  function Particle(){
    ...

这里有一个代码笔 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);
};