【问题标题】:Recommended way to redraw an html canvas from inside a loop using setTimeout [duplicate]使用 setTimeout 从循环内部重绘 html 画布的推荐方法 [重复]
【发布时间】:2013-04-01 20:25:58
【问题描述】:

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

【问题讨论】:

  • 为什么不把循环的内容放在超时调用的函数中,传递适当的 i 和 j 值作为参数?
  • @jonhopkins 当然,这将是另一种方法,但我认为这是一个偏好问题,可能与我的实际问题无关。
  • @apsillers 实际上我认为问题在那里没有解决(至少这不会解决我的问题),因为我需要在循环继续之前完成对函数 draw 的每次调用。我的代码以及链接问题的答案似乎是在 while 循环期间建立函数调用,并在一段时间后“一起”执行它们。 :o(

标签: javascript html animation canvas settimeout


【解决方案1】:

试试 RequestAnimationFrame!

RequestAnimationFrame 和 setTimeout 一样是异步的,比 setTimeout 更高效。

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

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

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

        // your draw() stuff goes here

    }, 1000 / fps);
}

【讨论】:

    【解决方案2】:

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

    这是一个简单的例子 -> 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);
        }    
    }
    

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

      • 我接受了这个,因为它保持了间隔,很少修改我的原始代码,并考虑到循环终止。 +1!
      猜你喜欢
      • 1970-01-01
      • 2010-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-10
      • 1970-01-01
      • 2013-10-13
      相关资源
      最近更新 更多