Javascript 在何处放置addEventListener,使其不会';不要多次开火

Javascript 在何处放置addEventListener,使其不会';不要多次开火,javascript,eventhandler,Javascript,Eventhandler,我有一个Javascript文件,它用圆圈绘制画布。如果我点击一个圆圈,颜色必须改变。这是可行的,但eventHandler只需单击一下就可以触发多次。正因为如此,该计划滞后了很多。我如何改进这一点 var cvs=document.getElementById(“canvas”); var ctx=cvs.getContext(“2d”); 班级圈子{ 构造函数(x、y、半径、颜色){ 这个.x=x; 这个。y=y; 这个半径=半径; 这个颜色=颜色; } draw=函数(){ ctx.be

我有一个Javascript文件,它用圆圈绘制画布。如果我点击一个圆圈,颜色必须改变。这是可行的,但eventHandler只需单击一下就可以触发多次。正因为如此,该计划滞后了很多。我如何改进这一点

var cvs=document.getElementById(“canvas”);
var ctx=cvs.getContext(“2d”);
班级圈子{
构造函数(x、y、半径、颜色){
这个.x=x;
这个。y=y;
这个半径=半径;
这个颜色=颜色;
}
draw=函数(){
ctx.beginPath();
ctx.arc(this.x,this.y,this.radius,0,2*Math.PI,false);
ctx.strokeStyle=this.color;
ctx.stroke();
};
更新=函数(){
cvs.addEventListener(“单击”,函数(e){
var mousePosition=this.getMousePosition(e);
检查碰撞(鼠标位置);
}.约束(这个);
这个.draw();
};
getMousePosition=函数(e){
var-cRect=cvs.getBoundingClientRect();
var canvasX=数学圆(e.clientX-正确的左);
var canvasY=数学圆(e.clientY-cRect.top);
返回{
x:画布,
y:拉票
}
}
checkForCollision=函数(mPos){
如果(mPos.xthis.x-this.radius&&mPos.ythis.y-this.radius){
this.color=“蓝色”;
}
}
}
var循环=[];
对于(x=0;x<8;x++){
对于(y=0;y<8;y++){
圆圈。推(新圆圈(x*100+30,y*100+30,20,“红色”);
}
}
函数playGame(){
请求动画帧(游戏);
ctx.clearRect(0,0,2000,2000);
circles.forEach(circle=>circle.update());
}
游戏()

当前,由于您调用的是
addEventListener
,所以在每个绘图周期都要添加一个事件侦听器。如果将
addEventListener
移动到圆的构造函数,则每个圆对象只会附加一次(在您的情况下,为64次):

var cvs=document.getElementById(“canvas”);
var ctx=cvs.getContext(“2d”);
班级圈子{
构造函数(x、y、半径、颜色){
这个.x=x;
这个。y=y;
这个半径=半径;
这个颜色=颜色;
cvs.addEventListener(“单击”,函数(e){
var mousePosition=this.getMousePosition(e);
检查碰撞(鼠标位置);
log('Click-detected!');
}.约束(这个);
}
draw=函数(){
ctx.beginPath();
ctx.arc(this.x,this.y,this.radius,0,2*Math.PI,false);
ctx.strokeStyle=this.color;
ctx.stroke();
};
更新=函数(){
这个.draw();
};
getMousePosition=函数(e){
var-cRect=cvs.getBoundingClientRect();
var canvasX=数学圆(e.clientX-正确的左);
var canvasY=数学圆(e.clientY-cRect.top);
返回{
x:画布,
y:拉票
}
}
checkForCollision=函数(mPos){
如果(mPos.xthis.x-this.radius&&mPos.ythis.y-this.radius){
this.color=“蓝色”;
}
}
}
var循环=[];
对于(x=0;x<8;x++){
对于(y=0;y<8;y++){
圆圈。推(新圆圈(x*100+30,y*100+30,20,“红色”);
}
}
函数playGame(){
请求动画帧(游戏);
ctx.clearRect(0,0,2000,2000);
circles.forEach(circle=>circle.update());
}
游戏()

当前,由于您调用的是
addEventListener
,所以在每个绘图周期都要添加一个事件侦听器。如果将
addEventListener
移动到圆的构造函数,则每个圆对象只会附加一次(在您的情况下,为64次):

var cvs=document.getElementById(“canvas”);
var ctx=cvs.getContext(“2d”);
班级圈子{
构造函数(x、y、半径、颜色){
这个.x=x;
这个。y=y;
这个半径=半径;
这个颜色=颜色;
cvs.addEventListener(“单击”,函数(e){
var mousePosition=this.getMousePosition(e);
检查碰撞(鼠标位置);
log('Click-detected!');
}.约束(这个);
}
draw=函数(){
ctx.beginPath();
ctx.arc(this.x,this.y,this.radius,0,2*Math.PI,false);
ctx.strokeStyle=this.color;
ctx.stroke();
};
更新=函数(){
这个.draw();
};
getMousePosition=函数(e){
var-cRect=cvs.getBoundingClientRect();
var canvasX=数学圆(e.clientX-正确的左);
var canvasY=数学圆(e.clientY-cRect.top);
返回{
x:画布,
y:拉票
}
}
checkForCollision=函数(mPos){
如果(mPos.xthis.x-this.radius&&mPos.ythis.y-this.radius){
this.color=“蓝色”;
}
}
}
var循环=[];
对于(x=0;x<8;x++){
对于(y=0;y<8;y++){
圆圈。推(新圆圈(x*100+30,y*100+30,20,“红色”);
}
}
函数playGame(){
请求动画帧(游戏);
ctx.clearRect(0,0,2000,2000);
circles.forEach(circle=>circle.update());
}
游戏()

您正在每个绘图周期添加一个新的单击事件,该事件的累积速度很快。尝试将addEventListener移动到绘图/更新周期之外

也可能导致功能多次启动。然而,这可以很容易地用

事件监听器在课堂之外。

var cvs=document.getElementById(“canvas”);
var ctx=cvs.getContext(“2d”);
班级圈子{
构造函数(x、y、半径、颜色){
这个.x=x;
这个。y=y;
这个半径=半径;
这个颜色=颜色;
}
draw=函数(){
ctx.be