Drawing multiple offscreen canvases into onscreen canvas

I am having an issue when I'm trying to render multiple offscreen canvases into onscreen canvas. I do get one offscreen canvas rendered but the problem is that there should be two other rendered before. In other words, only last canvas is rendered. The expected result would be three overlapping rectangles (or squares :) in red, green and blue. Here's the code:

function rectangle(color) {
    var offScreenCanvas = document.createElement('canvas');
    var offScreenCtx = offScreenCanvas.getContext('2d');

    var width = offScreenCanvas.width = 150;
    var height = offScreenCanvas.height = 150;

    switch(color) {
        case 1: 
            offScreenCtx.fillStyle='rgb(255,0,0)';
            break;
        case 2:
            offScreenCtx.fillStyle='rgb(0,255,0)';
            break;
        case 3:
            offScreenCtx.fillStyle='rgb(0,0,255)';
            break;
    }

    offScreenCtx.fillRect(0,0,width,height);

return offScreenCanvas;
}

function draw(offScreenCanvas, x , y) {
    var canvas = document.getElementById('canvas')
    var ctx = canvas.getContext('2d');

    var width = canvas.width = window.innerWidth;
    var height = canvas.height = window.innerHeight;

    ctx.drawImage(offScreenCanvas, x, y);
}

var images = [];
var color = 1;

for (var i=0; i<3; i++) {
    var img = new rectangle(color);
    images.push(img);
    color++;
}

var x = 0;
var y = 0;

for (var i = 0; i < images.length; i++) {
    draw(images[i], x, y);
    x += 100;
    y += 100;
}

I did some searching and it seems that I'm not the first with this issue, but I could not get this working properly.

1 answer

  • answered 2017-06-17 19:00 Blindman67

    Setting canvas height or width clears the canvas.

    The problem with your code is that you are causing the onscreen canvas to be cleared when you set it size in the function draw

    Setting the canvas size, even if that size is the same, will cause the canvas context to reset and clear the canvas. All the other canvases are rendered, but erased when you set the onscreen canvas size.

    Your draw function

    function draw(offScreenCanvas, x , y) {
        var canvas = document.getElementById('canvas')
        var ctx = canvas.getContext('2d');
    
        // The cause of the problem ===================================
        // Either one of the following lines will clear the canvas
        var width = canvas.width = window.innerWidth;
        var height = canvas.height = window.innerHeight;
        //=============================================================
    
        ctx.drawImage(offScreenCanvas, x, y);
    }
    

    To avoid this just set the canvas size once. If you need to resize the canvas and keep its content you first need to create a copy of the canvas, then resize it, then render the copy back to the original.

    Demo shows 5 offscreen canvases being rendered onto one onscreen canvas.

    const colours = ['#f00', '#ff0', '#0f0', '#0ff', '#00f'];
    const ctx = can.getContext('2d');
    can.width = innerWidth - 4;  // sub 4 px for border
    can.height = innerHeight - 4;
    
    function createCanvas(color, i) {
      const canvas = document.createElement('canvas');
      const ctx = canvas.getContext('2d');
      canvas.width = 150;
      canvas.height = 150;
      ctx.font = "24px arial";
      ctx.fillStyle = color;
      ctx.fillRect(0, i * 30, canvas.width, 30);
      ctx.fillStyle = "black";
      ctx.fillText("Canvas "+i,10,(i + 0.75) * 30);
      return canvas;
    }
    colours.forEach((c, i) => {
      ctx.drawImage(createCanvas(c, i), 0, 0);
    })
    canvas {
      border: 2px solid black;
      position : absolute;
      top : 0px;
      left : 0px;
    }
    <canvas id="can"></canvas>