【问题标题】:clearRect not working?清除矩形不起作用?
【发布时间】:2013-11-02 14:11:40
【问题描述】:

我是一个非常初学者的网页设计师,我对这段代码有两个问题。

<!DOCTYPE html>
<html>
<head>
<style type="text/css">
#canvas1{border: #666 3px solid;}
</style>
<script type="application/javascript" language="javascript">
function draw (x,y){
var canvas = document.getElementById('canvas1');
var ctx = canvas.getContext('2d');
ctx.save();
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillstyle = "rgb (0,200, 0)";
ctx.fillRect(x, 20, 50, 50);
ctx.restore();
x += 5;
var loop = setTimeout('draw('+x+', '+y+')', 100); 
}
</script>
</head>
<body>
<button onclick="draw(0,0)">Start</button>
<canvas id="canvas1" width="400" height="400"</canvas>
</body>
</html>

为什么方块总是变黑?以及为什么如果我再次尝试按开始,clearRect 功能不起作用?

【问题讨论】:

  • 从不将字符串传递给setInterval()setTimeout()。这样做与使用eval() 一样糟糕,一旦使用变量,它就会导致代码不可读且可能不安全,因为您需要将它们插入字符串而不是传递实际变量。正确的解决方案是setInterval(function() { /* your code *) }, msecs);。这同样适用于setTimeout()。如果只想调用单个函数不带任何参数,也可以直接传函数名:setInterval(someFunction, msecs);(注意函数名后面有no()
  • 它调用了一个函数,函数draw。
  • 你没有明白我的意思。您应该传递一个实际函数:setTimeout(function() { draw(x, y); }, 100);,或者如果您只需要支持现代浏览器:setTimeout(draw.bind(this, x, y), 100);

标签: html canvas


【解决方案1】:

当您单击开始时,您将开始一个新的循环,该循环与已经开始的循环并行运行,并且取决于首先执行的循环,您的画布将被清除并填充两次(或者您启动循环的次数 - 越多越多发音会闪烁)。

您需要一种机制来防止循环多次启动。一种方法是使用标志。我还建议您重构代码,将循环和绘图分开:

Live demo here

/// put these outside, no need to re-allocate them each time
var canvas = document.getElementById('canvas1');
var ctx = canvas.getContext('2d');
var w = canvas.width;
var h = canvas.height;
var x = 0;
var isRunning = false;

/// all loop-related here:
function loop() {

    /// call draw from inside the loop instead
    draw(x, 0); /// you are never using y so I just set 0 here...

    x += 5;

    if (isRunning && x <= w) {
        requestAnimationFrame(loop);  /// this is a better alternative
        //setTimeout(loop, 100);      /// optionally, but not recommended
    } else {
        isRunning = false;  /// box is outside visible area so we'll stop..
    }
}

/// keep draw() "clean", no loop code in here:
function draw(x, y) {
    /// no need for save/restore here...
    ctx.clearRect(0, 0, w, h);
    ctx.fillStyle = "rgb(0, 200, 0)";
    ctx.fillRect(x, 20, 50, 50);
}

您的fillStyle 输入错误,您的rgb(... 必须没有空格(如另一个答案中所述 - 但在这种情况下只会导致填充样式为黑色),此外您还缺少一个html 中 canvas 标记的右括号。

要检查按钮点击,这是一种更推荐的方法,而不是在 html 中内联 JS:

/// check for button clicks (start):
document.getElementById('start').addEventListener('click', function() {

    if (!isRunning) {     /// are we running? if not start loop
        isRunning = true; /// set flag so we can prevent multiple clicks
        x = 0;            /// reset x
        loop();           /// now we start the *loop*
    }

}, false);

在你的 html 中:

<button id="start">Start</button>

现在您可以轻松制作暂停按钮:

<button id="stop">Stop</button>

并将其添加到脚本中:

document.getElementById('stop').addEventListener('click', function() {

    isRunning = false;

}, false);

【讨论】:

  • 谢谢!你的方法很有帮助,但我不得不搜索一些东西,因为我对 html 非常陌生(一般代码)。
【解决方案2】:

因为你需要使用:

ctx.fillStyle = "rgb(0,200,0)";

大写的“S”,“rgb”和左括号之间没有空格:http://jsfiddle.net/dtHjf/

那么,为什么多次按下“开始”会导致方块闪烁,那是因为每次按下它都会开始另一个动画循环,但不会取消旧循环,所以你有多个循环互相争斗。如果您确保在开始新循环之前取消任何预先存在的循环,您应该没问题:

http://jsfiddle.net/dtHjf/2/

HTML

<button id="startAnim">Start</button><br />
<canvas id="canvas1" width="400" height="400"></canvas>

JS

var canvas = document.getElementById('canvas1'),
    ctx = canvas.getContext('2d'),
    loop;

function draw(x, y) {

    ctx.save();
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = "rgb(0,200,0)";
    ctx.fillRect(x, 20, 50, 50);
    ctx.restore();

    x += 5;
    loop = setTimeout(function(){draw(x,y)}, 100);
}

document.getElementById('startAnim').onclick = function(){
    clearTimeout(loop);
    draw(0,0);
};

另外,这与你的问题无关,但你可能想看看requestAnimationFrame

https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/

【讨论】:

  • 你能告诉我为什么如果我再按开始,方形(矩形)会闪烁吗?我认为是因为 clearRect 不起作用,但你能告诉我如何解决它吗?
  • @matt729 是的,我已将其添加到我的答案中
  • 谢谢!这也很有帮助,而且更加简洁易懂!
猜你喜欢
  • 2012-04-02
  • 2015-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-24
  • 1970-01-01
相关资源
最近更新 更多