我在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;
答案 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。
但是对于图形来说,你应该使用的requestAnimationFrame
与setTimeout
非常相似,但是你没有提供超时,浏览器将获得最佳时间让你与渲染和布局引擎以及显示硬件,这样你就不会出现闪烁和剪切。
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
函数中使用这些值来处理鼠标。这样可以生成更易于管理的鼠标界面。