An example of using the canvas clip() function to create an animation

Written by Richard Heyes, on 7th April 2013

A guide explaining how to use the canvas tags clip() function to create a Reveal style effect where the canvas is incrementally revealed from the left-hand-side.

The clip() function can be used with great effectiveness to create a "Reveal" effect - where the canvas is slowly revealed - much like a curtain, that is hiding the canvas, is being drawn back.

1. The original canvas

This is the original canvas drawing before the effect has been created. All that is being done is some lines are being drawn.

[No canvas support]
<script>
    window.addEventListener('load', function ()
    {
        var ca = document.getElementById("cvs1");
        var co = ca.getContext('2d');
        
        // This clears the canvas allowing us to start from scratch
        ca.width = ca.width;
        
        co.save();
            co.beginPath();
            co.lineWidth = 5;
            co.lineCap = 'round';
            
            var coords = [
                          {x: 75, y:25},{x: 550, y:25},
                          {x: 75, y:50},{x: 550, y:50},
                          {x: 75, y:75},{x: 550, y:75},
                          {x: 75, y:100},{x: 550, y:100},
                          {x: 75, y:125},{x: 550, y:125},
                          {x: 75, y:150},{x: 550, y:150},
                          {x: 75, y:175},{x: 550, y:175},
                          {x: 75, y:200},{x: 550, y:200},
                          {x: 75, y:225},{x: 550, y:225}
                         ]
                         
            for (var i=0; i<coords.length; i+=2) {
                co.moveTo(coords[i].x, coords[i].y);
                co.lineTo(coords[i+1].x, coords[i+1].y);
            }
            
            co.stroke();
        co.restore();
    }, false);
</script>

2. The clipped canvas

Now, before the lines are drawn, a path is drawn that is used to clip the canvas. Here the path is a rectangle that starts on the left of the canvas and extends part way across it. Once the rectangle is drawn (but not stroked or filled) the clip() function can then be used so that any drawing outside of that rectangle is not actually painted on to the canvas. So the result is that only the first parts of the lines are shown.

The state of the canvas is saved before the clip is performed so that it can be restored afterwards (so the clip effect is removed).

[No canvas support]
<script>
    window.addEventListener('load', function ()
    {
        var ca = document.getElementById("cvs2");
        var co = ca.getContext('2d');
        
        // This clears the canvas allowing us to start from scratch
        ca.width = ca.width;
        
        co.save();

            // Before drawing the lines the canvas should be clipped
            co.beginPath;
            co.rect(0,0,300,250)
            co.clip();

            co.beginPath();
            co.lineWidth = 5;
            co.lineCap = 'round';
            
            var coords = [
                {x: 75, y:25},{x: 550, y:25},
                {x: 75, y:50},{x: 550, y:50},
                {x: 75, y:75},{x: 550, y:75},
                {x: 75, y:100},{x: 550, y:100},
                {x: 75, y:125},{x: 550, y:125},
                {x: 75, y:150},{x: 550, y:150},
                {x: 75, y:175},{x: 550, y:175},
                {x: 75, y:200},{x: 550, y:200},
                {x: 75, y:225},{x: 550, y:225}
            ];
                         
            for (var i=0; i<coords.length; i+=2) {
                co.moveTo(coords[i].x, coords[i].y);
                co.lineTo(coords[i+1].x, coords[i+1].y);
            }
            
            co.stroke();
        co.restore();
    }, false);
</script>

3. The animated and clipped canvas

Now, the clipped width is gradually increased from 0 to 600px, 10px at a time, at roughly 60fps thus giving the animation effect.


[No canvas support]
<script>
    var width = 0;

    Animate = function ()
    {
        var ca = document.getElementById("cvs3");
        var co = ca.getContext('2d');
        
        // This clears the canvas allowing us to start from scratch
        ca.width = ca.width;
        
        co.save();

            // Before drawing the lines the canvas should be clipped
            co.beginPath;
            co.rect(0,0,width,250)
            co.clip();

            co.beginPath();
            co.lineWidth = 5;
            co.lineCap = 'round';
            
            var coords = [
                {x: 75, y:25},{x: 550, y:25},
                {x: 75, y:50},{x: 550, y:50},
                {x: 75, y:75},{x: 550, y:75},
                {x: 75, y:100},{x: 550, y:100},
                {x: 75, y:125},{x: 550, y:125},
                {x: 75, y:150},{x: 550, y:150},
                {x: 75, y:175},{x: 550, y:175},
                {x: 75, y:200},{x: 550, y:200},
                {x: 75, y:225},{x: 550, y:225}
            ];
                         
            for (var i=0; i<coords.length; i+=2) {
                co.moveTo(coords[i].x, coords[i].y);
                co.lineTo(coords[i+1].x, coords[i+1].y);
            }
            
            co.stroke();
        co.restore();
        
        if (width < 600) {
            width += 10;
            UpdateCanvas(Animate);
        } else}
            width = 0;
        ]
    }
</script>

4. The UpdateCanvas() function

In case you're wondering what the UpdateCanvas() function is - it's a "shim" that wraps the requestAnimationFrame() function. Because the function is newer it may be only available via a prefixed version in some browsers.

<script>
        UpdateCanvas = function (func)
        {
            window.requestAnimationFrame =    window.requestAnimationFrame
                                           || window.webkitRequestAnimationFrame
                                           || window.msRequestAnimationFrame
                                           || window.amozRequestAnimationFrame
                                           || (function (func){setTimeout(func, 16.666);});
            
            window.requestAnimationFrame(func);
        }
</script>