Jordan
Jordan

Reputation: 9901

Canvas doesn't draw Images correctly on first draw

I have been experiencing bizarre behavior with the HTML5 Canvas in Chrome. As demonstrated in the example below, the images are not rendering correctly until the window is resized. All of the variables and properties have the exact same values both initially and on resize. Why does this happen?

Of course if the image hasn't loaded yet, the background won't display at all. You may need to refresh a few times.

<html>
<head>
</head>
<body>
<canvas id="test-canvas"></canvas>
</body>
<script>
    var canvas = document.querySelector('#test-canvas');
    var backgroundImage = new Image(100, 100);

    backgroundImage.src = 'https://via.placeholder.com/100';

    var dimensions = [];
    var center = [];
    var viewBox = [];

    function paint() {
      var ctx = canvas.getContext('2d');

      dimensions = [canvas.width, canvas.height];
      center = [dimensions[0] / 2, dimensions[1] / 2];
      viewBox = [
        -center[0], -center[1],
        center[0], center[1],
      ];

      ctx.translate(center[0], center[1]);

      paintBackground(ctx);
    }

    function paintBackground(ctx) {
      ctx.save();

      var size = [100, 100]

      var box = [
        Math.floor(viewBox[0] / size[0]) * size[0],
        Math.floor(viewBox[1] / size[1]) * size[1],
        Math.ceil(viewBox[2] / size[0]) * size[0],
        Math.ceil(viewBox[3] / size[1]) * size[1],
      ];

      for (let x = box[0]; x < box[2]; x += size[0]) {
        for (let y = box[1]; y < box[3]; y += size[1]) {
          ctx.drawImage(backgroundImage, x, y, size[0], size[1]);
        }
      }

      ctx.restore();
    }

    function resize() {
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;

        paint();
    }

    window.addEventListener('resize', resize);
    resize();

    setTimeout(paint, 200); 

</script>
</html>

The images should be covering the entire canvas...

enter image description here

But initially they only cover the lower right quadrant...

enter image description here

Upvotes: 0

Views: 33

Answers (1)

Jordan
Jordan

Reputation: 9901

I figured it out. I was translating every time I painted. I realized I needed to put a call to save and restore within my paint method. This solved my problem.

function paint() {
  var ctx = canvas.getContext('2d');
  ctx.save() // <--- here!

  dimensions = [canvas.width, canvas.height];
  center = [dimensions[0] / 2, dimensions[1] / 2];
  viewBox = [
    -center[0], -center[1],
    center[0], center[1],
  ];

  ctx.translate(center[0], center[1]);

  paintBackground(ctx);

  ctx.restore() // <--- and here!
}

Upvotes: 1

Related Questions