为什么鼠标移动会影响Javascript中的间隔?

为什么鼠标移动会影响Javascript中的间隔?,javascript,jquery,html,canvas,mouse,Javascript,Jquery,Html,Canvas,Mouse,我已经用JS编写了一些代码,允许用户在屏幕上单击创建一个正方形,并在压印之前按住鼠标以增加正方形的大小。问题是,当鼠标从最初单击的位置移动时,按住鼠标时正方形大小增加的速度会减慢。我正在使用间隔在1毫秒的时间内更改大小。以下是JS代码(带Jquery): 更新:如果运行代码段,则不会看到问题。尝试将其保存为文件并运行,则问题可能会出现 我的画布 $(函数(){ var mouseDown var c=document.getElementById('myCanvas'); var ctx=c

我已经用JS编写了一些代码,允许用户在屏幕上单击创建一个正方形,并在压印之前按住鼠标以增加正方形的大小。问题是,当鼠标从最初单击的位置移动时,按住鼠标时正方形大小增加的速度会减慢。我正在使用间隔在1毫秒的时间内更改大小。以下是JS代码(带Jquery):

更新:如果运行代码段,则不会看到问题。尝试将其保存为文件并运行,则问题可能会出现


我的画布
$(函数(){
var mouseDown
var c=document.getElementById('myCanvas');
var ctx=c.getContext(“2d”);
变量对象=[]
c、 addEventListener(“mousedown”,onMouseDown);
c、 addEventListener(“mouseup”,onMouseUp);
函数createSquare(x,y,size){
这个.x=x;
这个。y=y;
这个。大小=大小;
this.draw=draw;
this.drawStylus=drawStylus;
this.clear=clear;
};
函数绘图(){
ctx.fillRect(this.x,this.y,this.size,this.size);
};
函数drawStylus(){
ctx.fillRect(this.x,this.y,this.size,this.size);
};
函数clear(){
clearRect(this.x,this.y,this.size,this.size);
}
//var mySquare=new createSquare(100100);
//mySquare.draw();
函数onMouseDown(){
mouseDown=true
x=event.clientX
y=event.clientY
尺寸=100
console.log('clicked')
间隔=设置间隔(函数(){
尺寸=尺寸+5
var cursorSquare=新的createSquare(x,y,大小);
cursorSquare.clear();
游标方形绘图笔();
}, 1);
};
函数onMouseUp(){
console.log('up')
如果(鼠标向下){
间隔时间;
var newSquare=newcreatesquare(x,y,size);
newSquare.draw();
mouseDown=false
};
};
});

问题在于时间间隔

首先。1毫秒对于任何渲染来说都太短了,鼠标仅在1/60秒左右更新,超过1/60秒(较短时间)的渲染将给浏览器带来过重的负载,并且由于屏幕刷新也是在1/60秒,大多数渲染将在有机会进入显示之前丢失

其次,尽管1毫秒对于某些浏览器来说太短(忘记每个浏览器的最小间隔时间),但问题是,当您呈现的任务超过间隔时间时,浏览器仍会将函数调用添加到调用堆栈中,从而有效地延迟了其他事件和浏览器维护。在这种情况下继续使用setInterval将导致调用堆栈溢出,使页面上的所有javascript崩溃

最简单的规则是永远不要出于任何原因使用
setInterval
。请改用
setTimeout
,因为它可以防止调用堆栈溢出,并阻止调用堆栈上放置不受控制的调用。使用
setTimeout
实际上可以产生更好的定时间隔

// simple timeout
var interval = 50
function myTimer(){
     setTimeout(myTimer,interval); // set up the next interval
}
// start it
setTimeout(myTimer,interval);
通过
new Date().valueOf()
获取时间,您可以调整下一次调用的超时时间,使其尽可能接近所需的时间间隔,这是setInterval很难做到的。要停止调用,只要在设置停止标志时不调用setTimeout即可

但所有这些都表明,对于图形,您应该使用与设置超时非常类似的
requestAnimationFrame
,但您不提供超时,浏览器将获得最佳时间,使您与渲染和布局引擎以及显示硬件保持同步,从而避免闪烁和/或剪切

function update(time){ // requestAnimationFrame calls the function with the time in milliseconds
    // do what is needed
    requestAnimationFrame(update);  // get next frame when browser is ready 1/60th second
}
requestAnimationFrame(update);  // start it going 

为了与鼠标进行协调,只需让鼠标侦听器设置一些变量,如
mouseX
mouseY
buttonState
,而无需执行其他操作。在
update
函数中,使用这些值来处理鼠标。这将产生一个更易于管理的鼠标界面。

当我运行代码片段时,我看不到您所说的速度变慢。它似乎只在直接从我的电脑打开的文件中起作用。如果您尝试将代码片段粘贴到HTML文件中,在Chrome中打开它,你可能会看到我的问题。我也看不到它-从一个使用Chrome粘贴内容的文件中。我看到了。您必须按住鼠标(不移动鼠标),正方形的大小将增加。现在,当鼠标变大时,请尝试摆动/移动鼠标。它随意增加的速度会变慢。没有尝试过你的代码,但是通过阅读它,你会发现很多控制台错误,这可能是导致速度变慢的原因。了解闭包和对象声明。感谢Blindman67,这很有效。但我在这里遇到了另一个问题,可能与动画帧有关: