Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/392.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用setTimeout从循环内部重新绘制html画布的推荐方法_Javascript_Html_Animation_Canvas_Settimeout - Fatal编程技术网

Javascript 使用setTimeout从循环内部重新绘制html画布的推荐方法

Javascript 使用setTimeout从循环内部重新绘制html画布的推荐方法,javascript,html,animation,canvas,settimeout,Javascript,Html,Animation,Canvas,Settimeout,我已经研究了很多,主要是在SO中,关于setTimeout是“不阻塞”的,因此不适合在for循环中使用,因为循环一直在进行,而函数调用不断累积 我有一个HTML文件,它记录了一个图像处理算法,所以我想以“人类可读”的速度显示活动像素“行走”。我尝试过但不起作用的实现如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> </head> <body on

我已经研究了很多,主要是在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>

函数运行(){
重新评估();
};
固定中心变量;
var fixedcenterj;
函数重新评估(){
var altura_imagem=50;
var largura_imagem=40;
对于(var i=0;i
最简单的实现是将所有绘制命令存储在一个数组中,然后使用
setTimeout
在绘制命令之间等待来处理该数组

下面是一个快速示例->

然后

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

    var drawCommand = drawCommands[index];

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

我想这正是你想要的

<!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>

var fixedcenteri=0;
var fixedcenterj=0;
函数图(){
var elem=document.getElementById('Canvas');
var cx=elem.getContext('2d');
w=元素宽度;
h=元素高度;
cx.fillStyle=“白色”;
cx.fillRect(0,0,w,h);
cx.fillStyle='蓝色';
cx.fillRect(fixedcenteri,fixedcenterj,10,10);
如果(固定中心i<50){
如果(固定中心J<40){
fixedcenterj++;
}否则{
固定中心j=0;
fixedcenteri++;
}
设置超时(绘图,100);
}
}

试试RequestAnimationFrame

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

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

您甚至可以使用此技术将其调节到所需的FPS:

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

        // your draw() stuff goes here

    }, 1000 / fps);
}

为什么不把循环的内容放在一个在超时时被调用的函数中,把i和j的适当值作为参数传递呢?@jonhopkins这当然是另一种方法,但我认为这是一种偏好,而且可能与我的实际问题无关。@实际上,我认为问题没有解决(至少这不会解决我的问题),因为我需要在循环继续之前完成对函数
draw
的每次调用。我的代码和链接问题的答案似乎是在while循环期间建立函数调用,并在超时后“一起”执行它们:o(我接受了这个,因为它保持了间隔,很少修改我的原始代码,并且解释了循环终止。+1!
var fps = 15;
function draw() {
    setTimeout(function() {
        requestAnimationFrame(draw);

        // your draw() stuff goes here

    }, 1000 / fps);
}