An example of how to use the canvas clip function

Recommend RGraph:  
    Read comments... Posted on 29th January 2013

Summary
A guide explaining how to use the canvas 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 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 clip region

To reset the clip 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 clipped 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 - 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 apperance 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 RGraph Bar chart - which as the name suggests gives a bevelled appearance to your bars: http://www.rgraph.net/examples/bar.html

Related

Comments