Using the canvas globalCompositeOperation setting to achieve background and foreground layers

Recommend RGraph:  
    Read comments... Posted on 4th May 2013

Summary
HTML5 canvas doesn't support layers. But by using the canvas globalCompositeOperation setting you can achieve a limited foreground/background layering effect.

When working with canvas one thing that you need to understand is that there's no concept of layers. You'd do well to imagine the canvas as a piece of paper on to which you can draw - and once you've drawn on to it that drawing is mixed in with what was already on the canvas and a reference to it is not kept.

There is a way to draw something "behind" what is already on the canvas however by using the globalCompositeOperation option. This property defaults to "source-over" - which means that new drawings are placed over the existing content - just like drawing on paper.

You can change this however to "destination-over" so that new drawings are placed "behind" any existing content. The canvas below starts with a Bar chart being drawn - and then when the button is pressed a shape is drawn behind the chart. The source code for it is shown below.

[No canvas support]

<script>
    window.onload = function (e)
    {
        /**
        * Draw the bar chart
        */
        var bar = new RGraph.Bar({
            id: 'cvs',
            data: [4,8,6,3,5,4,2],
            options: {
                labels: ['John','Luis','Pete','Olga','Mabel','Mark','Luis'],
                textAccessible: true
            }
        }).draw();
        
        /**
        * This is the function that is triggered when the button is pressed. It sets the globalCompositeOperation
        * and draws the gray polygon
        */
        drawBackgroundImage = function ()
        {
            var context = bar.context;

            context.globalCompositeOperation = 'destination-over';
            
            context.beginPath();
            context.strokeStyle = '#ccc';
            context.fillStyle = '#efefef';
            
            context.moveTo(50,50);
            context.lineTo(50,200);
            context.lineTo(450,200);
            context.lineTo(450,50);
            context.lineTo(250,100);
            context.closePath();
            
            context.stroke()
            context.fill()
            
            // Reset the composite operation back to the default
            context.globalCompositeOperation = 'source-over';
        }
    }
        
</script>

<button onclick="drawBackgroundImage()">Draw a shape behind the chart</button>

Comments