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

时间:2016-03-20 02:23:07

标签: javascript jquery html canvas mouse

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

更新:如果您运行代码段,则无法查看问题。尝试将其保存为文件并运行它,然后可能会出现问题。



<!DOCTYPE html>

<html>

<head>
	<title>My Canvas</title>

	<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>

	<script type="text/javascript">
	$(function () {

		var mouseDown
		var c = document.getElementById('myCanvas');
		var ctx = c.getContext("2d");
		var objects = []

		c.addEventListener("mousedown", onMouseDown);
		c.addEventListener("mouseup", onMouseUp);

		function createSquare(x, y, size) {
			this.x = x;
			this.y = y;
			this.size = size;
			this.draw = draw;
			this.drawStylus = drawStylus;
			this.clear = clear;
		};

		function draw() {
			ctx.fillRect(this.x, this.y, this.size, this.size);
		};

		function drawStylus() {
			ctx.fillRect(this.x, this.y, this.size, this.size);
		};

		function clear() {
			ctx.clearRect(this.x, this.y, this.size, this.size);
		}

	//	var mySquare = new createSquare(100,100,100);
	//	mySquare.draw();

		function onMouseDown() {
			mouseDown = true
			x = event.clientX
			y = event.clientY
			size = 100
			console.log('clicked')

			interval = setInterval(function () {
				size = size + 5
				var cursorSquare = new createSquare(x,y,size);
				cursorSquare.clear();
				cursorSquare.drawStylus();
			}, 1);
		};

	   function onMouseUp() {
		   console.log('up')
		   if (mouseDown) {
		     clearInterval(interval);
		     var newSquare = new createSquare(x,y,size);
		     newSquare.draw();
		     mouseDown = false
			};
	};
	});
	</script>

</head>

<body>

<canvas id='myCanvas' width="5000" height="5000" style="border:1px solid #000000;">
	
</canvas>

</body>

</html>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:1)

问题是间隔,

首先。对于任何渲染,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。

但是对于图形来说,你应该使用的requestAnimationFramesetTimeout非常相似,但是你没有提供超时,浏览器将获得最佳时间让你与渲染和布局引擎以及显示硬件,这样你就不会出现闪烁和剪切。

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 

为了与鼠标协调,只需让您的鼠标听众设置一些变量,例如mouseXmouseYbuttonState,不做任何其他操作。在update函数中使用这些值来处理鼠标。这样可以生成更易于管理的鼠标界面。