每次调用绘图函数后,如何保持对象位置呈指数级增长?

问题描述:

简单的动画,在每次点击时在画布上创建类似焰火的效果。问题是动画是用setInterval(draw)制作的,每次画布被重绘时,每个粒子的位置是+ = particle.speed。但随着每次点击,粒子的移动速度越来越快,因为似乎每个粒子的速度都没有被重置。每次调用绘图函数后,如何保持对象位置呈指数级增长?

正如你可以看到几个点击working example here:,第一次点击的粒子移动非常(正确)缓慢,但随着每一次点击的速度增加。

所用的JS也粘贴在下面,任何帮助,非常感谢!

var canvas = document.getElementById("canvas"); 
    var ctx = canvas.getContext("2d"); 


    canvas.addEventListener("click", startdraw, false); 


    //Lets resize the canvas to occupy the full page 
    var W = window.innerWidth; 
    var H = window.innerHeight; 
    canvas.width = W; 
    canvas.height = H; 


    ctx.fillStyle = "black"; 
    ctx.fillRect(0, 0, W, H); 

    //global variables 
    var radius; 
    radius = 10; 
    balls_amt = 20; 
    balls = []; 

    var locX = Math.round(Math.random()*W); 
    var locY = Math.round(Math.random()*H); 


    //ball constructor 
    function ball(positionx,positiony,speedX,speedY) 
    { 
     this.r = Math.round(Math.random()*255); 
     this.g = Math.round(Math.random()*255); 
     this.b = Math.round(Math.random()*255); 
     this.a = Math.random(); 
     this.location = { 
      x: positionx, 
      y:positiony 
     } 
     this.speed = { 
      x: -2+Math.random()*4, 
      y: -2+Math.random()*4 
     }; 

    } 




    function draw(){ 

     ctx.globalCompositeOperation = "source-over"; 
     //Lets reduce the opacity of the BG paint to give the final touch 
     ctx.fillStyle = "rgba(0, 0, 0, 0.1)"; 
     ctx.fillRect(0, 0, W, H); 

     //Lets blend the particle with the BG 
     //ctx.globalCompositeOperation = "lighter"; 

     for(var i = 0; i < balls.length; i++) 
     { 
      var p = balls[i]; 
      ctx.beginPath(); 
      ctx.arc(p.location.x, p.location.y, radius, Math.PI*2, false); 
      ctx.fillStyle = "rgba("+p.r+","+p.g+","+p.b+", "+p.a+")"; 

      ctx.fill(); 
      var consolelogX = p.location.x; 
      var consolelogY = p.location.y; 
      p.location.x += p.speed.x; 
      p.location.y += p.speed.y; 


     } 
    } 
    function startdraw(e){ 

     var posX = e.pageX;  //find the x position of the mouse 
     var posY = e.pageY;  //find the y position of the mouse 
     for(i=0;i<balls_amt;i++){ 
      balls.push(new ball(posX,posY)); 
     } 

     setInterval(draw,20); 
     //ball[1].speed.x; 
    } 

后每次点击startdraw叫,开始每次为draw方法一个新的定期调用(setInterval)。所以在第二次点击之后,你有两个平行的间隔,在第三个之后你有三个平行的间隔。 它不是指数增长,仅线性增加:)

一个可能的脏修复: 介绍一个interval全局变量,并替换该行:

  setInterval(draw,20); 

这一个:

 if (!interval) interval = setInterval(draw,20); 

或者更好的解决方案是在onLoad事件中启动间隔。

setInterval将每隔20毫秒重复其呼叫,并返回一个ID。 您可以通过调用clearInterval(ID)来停止重复。

var id = setInterval("alert('yo!');", 500); 
clearInterval(id);