An example of how to use the canvas tags clip() function

Written by Richard Heyes, on 29th January 2013

A guide explaining how to use the canvas tags clip() function. The clip() function can be used to restrict the area of the canvas that drawings show up on. By default the whole canvas can be drawn on.

The clip() function is a lesser known function that can be very useful when drawing on your canvas. You can create a path but not fill or stroke it and then use the clip() function so that any further drawing is restricted to that area. There's a step-by-step example of using it below. One common use for it would be to achieve "inner shadows" - as in the circle shown below - meaning that you get a bevelled appearance.

1. The original canvas

This is the original canvas drawing before the clip() method is applied. As you can see all that's happening is a filled black rectangle that covers the whole of the canvas is being drawn.

[No canvas support]
<script>
    window.onload = function ()
    {
        var context = document.getElementById("cvs").getContext('2d');
        context.beginPath();
        context.fillStyle = 'black'
        context.rect(0,0,600,250);
        context.fill()
    }
</script>

2. Draw a path before the fill is performed and clip() to it

Now, before the fill happens, we're going to draw a path and clip() the canvas to it. Any further drawing (ie the fill) will then be restricted to it - so, as you can see from the canvas below, only the circle ends up being colored black.

[No canvas support]
<script>
    window.onload = function ()
    {
        var context = document.getElementById("cvs").getContext('2d');

        // Draw the path that is going to be clipped
        context.beginPath();
        context.arc(300,125,50, 0, 2 * Math.PI, false);
        // Don't stroke or fill it
        
        // Now clip the canvas
        context.clip();

        context.beginPath();
        context.fillStyle = 'black'
        context.rect(0,0,600,250);
        context.fill()
    }
</script>

3. Reset the clipping region

To reset the clipping region after you finish with it you can save the state of the canvas before you clip it and then restore it when you're done.

What you can't do is simply change the clipping region by setting it again to a larger area. This is because the clip() calls are additive - so if in the red circle example below you draw the bevelled circle and then clip the canvas again to [0,0,300,250] (the first half of the canvas) the resulting area that ends up being clipped is the first half of the circle (the first half of the initial circle plus the rectangle).

<script>
    window.onload = function ()
    {
        var context = document.getElementById("cvs").getContext('2d');
        
        context.save();
            // Draw the path that is going to be clipped
            context.beginPath();
            context.arc(300,125,50, 0, 2 * Math.PI, false);
            // Don't stroke or fill it
            
            // Now clip the canvas
            context.clip();
    
            context.beginPath();
            context.fillStyle = 'black'
            context.rect(0,0,600,250);
            context.fill();
        context.restore();
        
        // Further drawing will not be restricted
    }
</script>

The resetClip() function

In March 2012 the canvas v5 spec was published and this had a resetClip() function as part of it. The resetClip() function replaces (instead of adding to the current clipping region) the clip region with one that starts at [0,0] and extends for the width and height of the canvas - effectively clearing any previous clipping region.

context.resetClip();

What can clip() be used for?

One possible use is for "inner shadows" - which results in a bevelled appearance as below.

[No canvas support]
<script>
    window.onload = function ()
    {
        var context = document.getElementById("cvs").getContext('2d');
        
        context.save();
            // Draw the path that is going to be clipped
            context.beginPath();
            context.arc(300,125,50, 0, 2 * Math.PI, false);
            // Don't stroke or fill it

            // Now clip the canvas
            context.clip();
            
            // Fill the canvas
            context.beginPath();
            context.fillStyle = 'red'
            context.rect(0,0,600,250);
            context.fill();
        
            // Draw a circle that has a shadow just outside of the clipped area so
            // that the shadow falls inside of the clipped area
            context.beginPath();
            context.lineWidth = 4;
            context.shadowColor   = 'black';
            context.shadowBlur    = 15;
            context.shadowOffsetX = 0;
            context.shadowOffsetY = 0;
            context.arc(300,125,52, 0, 2 * Math.PI, false);
            context.stroke();
        context.restore();
    }
</script>

An example of this effect is the bevel option for the Bar chart - which as the name suggests gives you a bevelled appearance to your bars.

Related