每次调用绘图函数后,如何保持对象位置呈指数级增长?
问题描述:
简单的动画,在每次点击时在画布上创建类似焰火的效果。问题是动画是用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);