положитьImageData на цикл - PullRequest
       33

положитьImageData на цикл

0 голосов
/ 01 декабря 2018

Я пытаюсь создать красивое графическое изображение (анимированное!), Вычисляя цвет для каждого пикселя на экране и затем показывая все пиксели одновременно.Итак, я использую функцию putImageData в цикле.

Но по какой-то причине это не работает.На экране видна только последняя итерация (через 1-2 секунды).

Я пытался использовать FillRect после каждой итерации, но это не помогло.

<html>
<head>
    <title>Full Screen Canvas Test</title>
    <style>
        html, body {
            overflow: hidden;
            margin: 0;
        }
    </style>
</head>
<body>

    <canvas id="mainCanvas"></canvas>

    <script>
        (function () {
            canvas = document.getElementById('mainCanvas');
            ctx = canvas.getContext("2d");              
            canvas.width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
            canvas.height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
            step = 1;

            function doit() {   
                rx = Math.floor(Math.random()*canvas.width);
                ry = Math.floor(Math.random()*canvas.height);
                gx = Math.floor(Math.random()*canvas.width);
                gy = Math.floor(Math.random()*canvas.height);
                bx = Math.floor(Math.random()*canvas.width);
                by = Math.floor(Math.random()*canvas.height);                                               

                var canvasData = ctx.createImageData(canvas.width, canvas.height);

                for (var i = 0; i < canvas.width; i+=step) {
                    for (var j = 0; j < canvas.height; j+=step) {
                        po = 2;
                        rd = Math.floor(Math.sqrt(Math.pow(rx - i, po)+Math.pow(ry - j, po)));
                        gd = Math.floor(Math.sqrt(Math.pow(gx - i, po)+Math.pow(gy - j, po)));
                        bd = Math.floor(Math.sqrt(Math.pow(bx - i, po)+Math.pow(by - j, po)));
                        maxd = 1400;
                        r = Math.floor((1 - rd/maxd)*255);
                        g = Math.floor((1 - gd/maxd)*255);
                        b = Math.floor((1 - bd/maxd)*255);

                        var index = (i + j * canvas.width) * 4;

                        canvasData.data[index + 0] = r;
                        canvasData.data[index + 1] = g;
                        canvasData.data[index + 2] = b;
                        canvasData.data[index + 3] = 255;


                    }
                }

                ctx.putImageData(canvasData, 0, 0);

            }       

            doit();
            doit();
            doit();
            doit();
            doit();
            doit();
            doit();
            doit();
        })();
    </script>
</body>

1 Ответ

0 голосов
/ 01 декабря 2018

Вам нужно использовать setInveral() для вызова функции doit() несколько раз с задержкой между вызовами.Проблема с вашим текущим методом заключается в том, что он запускает все ваши doit() результаты за одну итерацию, а затем отображает последнюю только тогда, когда она перезаписывает ваши предыдущие результаты.Таким образом, вам необходимо отображать результаты каждого последовательно.

См. Рабочий пример ниже:

<html>

<head>
  <title>Full Screen Canvas Test</title>
  <style>
    html,
    body {
      overflow: hidden;
      margin: 0;
    }
  </style>
</head>

<body>

  <canvas id="mainCanvas"></canvas>

  <script>
    (function() {
      canvas = document.getElementById('mainCanvas');
      ctx = canvas.getContext("2d");
      canvas.width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
      canvas.height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
      step = 1;

      function doit() {
        rx = Math.floor(Math.random() * canvas.width);
        ry = Math.floor(Math.random() * canvas.height);
        gx = Math.floor(Math.random() * canvas.width);
        gy = Math.floor(Math.random() * canvas.height);
        bx = Math.floor(Math.random() * canvas.width);
        by = Math.floor(Math.random() * canvas.height);

        var canvasData = ctx.createImageData(canvas.width, canvas.height);

        for (var i = 0; i < canvas.width; i += step) {
          for (var j = 0; j < canvas.height; j += step) {
            po = 2;
            rd = Math.floor(Math.sqrt(Math.pow(rx - i, po) + Math.pow(ry - j, po)));
            gd = Math.floor(Math.sqrt(Math.pow(gx - i, po) + Math.pow(gy - j, po)));
            bd = Math.floor(Math.sqrt(Math.pow(bx - i, po) + Math.pow(by - j, po)));
            maxd = 1400;
            r = Math.floor((1 - rd / maxd) * 255);
            g = Math.floor((1 - gd / maxd) * 255);
            b = Math.floor((1 - bd / maxd) * 255);

            var index = (i + j * canvas.width) * 4;

            canvasData.data[index + 0] = r;
            canvasData.data[index + 1] = g;
            canvasData.data[index + 2] = b;
            canvasData.data[index + 3] = 255;

          }
        }

        ctx.putImageData(canvasData, 0, 0);
      }
      
      // Use setInterval to display the images sequentially (every 1000 m/s (every second))
      let showImg = setInterval(doit, 1000);
    })();
  </script>
</body>
...