Search code examples
javascriptsortingcanvaslayer

Sorting objects on canvas


I draw two bottons using a rectangle with text over top. As you can see I get two different results using the same loop. The first "button" has the text hidden behind the box. The second has the text written on top. Why is this? How does sorting work in canvas?

<body>
  <canvas id="canvas" width="320" height="512"
  style="position: absolute; left: 500px; top: 50px; z-index: 1;"></canvas>
<script>
var canvas = document.getElementById('canvas');
var context = canvas.getContext("2d");
canvas.style.backgroundColor = 'rgba(0, 0, 0, 0)';
context.clearRect(0, 0, 320, 16);
gameMenu();

function gameMenu(){
var buttons = [ {x: 210, y: 420, w: 80, h: 30, s: "Messages"},
              {x: 210, y: 470, w: 80, h: 30, s: "Pause"} ], i = 0, r;

    while(r = buttons[i++]) {
    context.rect(r.x, r.y, r.w, r.h);
    context.fillStyle = "rgb(26,26,26)";
    context.fill();

    context.fillStyle = 'White';
    context.font = "16px Tahoma";
    context.fillText(r.s, r.x + 18, r.y + 22);
    }
}
</script>
</body>

Here is a JS Fiddle: https://jsfiddle.net/oa84Lsxn/1/


Solution

  • You must begin each new path operation (==each new .rect) with context.beginPath. Otherwise all previous .rects will be redrawn along with the current .rect.

    Your issue is that all previous paths are redrawn along with the new path. This means your first rect is being redrawn along with your new second rect -- causing the first rect's text to be overwritten by the first rect.

    Here's a working version your code with context.beginPath added.

    var canvas=document.getElementById("canvas");
    var context = canvas.getContext("2d");
    canvas.style.backgroundColor = 'rgba(0, 0, 0, 0)';
    context.clearRect(0, 0, 320, 16);
    gameMenu();
    
    function gameMenu(){
    // x,y changed to fit demo on StackSnipped window
    var buttons = [ {x: 40, y: 20, w: 80, h: 30, s: "Messages"},
                  {x: 40, y: 70, w: 80, h: 30, s: "Pause"} ], 
                  i = 0, r;
    
        while(r = buttons[i++]) {
            context.beginPath();
            context.rect(r.x, r.y, r.w, r.h);
            context.fillStyle = "rgb(26,26,26)";
            context.fill();
    
            context.fillStyle = 'White';
            context.font = "16px Tahoma";
            context.fillText(r.s, r.x + 18, r.y + 22);
        }
    
    }
    #canvas{border:1px solid red; margin:0 auto; }
    <canvas id="canvas" width=300 height=300></canvas>