建议使用setTimeout从循环内重绘html画布的方法

时间:2013-04-01 20:25:58

标签: javascript html animation canvas settimeout

我已经研究了很多,主要是在SO中,关于setTimeout“没有阻塞”,因此不适合在for循环中使用,因为循环一直在继续,一个在函数调用时继续积累。

我有一个记录图像处理算法的HTML文件,因此我希望以“人类可读”的速度显示活动像素“行走”。我尝试过但不起作用的实现如下:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
</head>

<body onload="run();">

    <canvas id="Canvas" width=501 height=601></canvas>

    <script>

        function run() {
            reevaluate();
        };

        var fixedcenteri;
        var fixedcenterj;



        function reevaluate() {

            var altura_imagem = 50;
            var largura_imagem = 40;

            for (var i = 0; i < altura_imagem; i++) {
                for (var j = 0; j < largura_imagem; j++) {

                    fixedcenteri = i;
                    fixedcenterj = j;

                    setTimeout(draw, 100);


                    // if I uncomment this I can see what I want, but...
                    // alert(i+j);
                };
            };
        };


        function draw () {
            var elem = document.getElementById('Canvas');
            var cx = elem.getContext('2d');

            w = elem.width;
            h = elem.height;

            cx.fillStyle = "white";
            cx.fillRect(0,0,w,h);

            cx.fillStyle = 'blue';
            cx.fillRect(fixedcenteri, fixedcenterj, 10, 10);
        }

    </script>
</body>
</html>

3 个答案:

答案 0 :(得分:5)

尝试RequestAnimationFrame!

RequestAnimationFrame与setTimeout一样是异步的,它比setTimeout更有效。

此外,它还为离屏动画提供动画分组和自动停止功能。

您甚至可以使用此技术将其限制为所需的FPS:

var fps = 15;
function draw() {
    setTimeout(function() {
        requestAnimationFrame(draw);

        // your draw() stuff goes here

    }, 1000 / fps);
}

答案 1 :(得分:2)

最简单的实现方法是将所有绘制命令存储在一个数组中,然后使用setTimeout处理该数组,以便在绘制命令之间等待。

这是一个简单的例子 - &gt; http://jsfiddle.net/K4D84/

//in your initial loop instead of draw
drawCommands.push({i: i, j: j});

则...

function slowDraw(index) {
    index = index || 0;

    var drawCommand = drawCommands[index];

    if (drawCommand) {
        fixedcenteri = drawCommand.i;
        fixedcenterj = drawCommand.j;
        setTimeout(function () {
            draw();
            slowDraw(++index);
        }, 100);
    }    
}

答案 2 :(得分:0)

我认为这可以满足您的需求。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
</head>

<body onload="draw();">

    <canvas id="Canvas" width=501 height=601></canvas>

    <script>

        var fixedcenteri = 0;
        var fixedcenterj = 0;

        function draw () {
            var elem = document.getElementById('Canvas');
            var cx = elem.getContext('2d');

            w = elem.width;
            h = elem.height;

            cx.fillStyle = "white";
            cx.fillRect(0,0,w,h);

            cx.fillStyle = 'blue';
            cx.fillRect(fixedcenteri, fixedcenterj, 10, 10);

            if(fixedcenteri < 50) {
                if(fixedcenterj < 40) {
                    fixedcenterj++;
                } else {
                    fixedcenterj = 0;
                    fixedcenteri++;
                }
                setTimeout(draw, 100);
            }
        }

</script>