Important: The RGraph website has recently experienced some downtime. It's now back up and available once more but keep this in mind as you may experience errors or oddities when browsing the site.

The HTML5 canvas tag - an introduction to what it is

 

Introduction

<canvas> is a new HTML tag which is part of the HTML5 standard. It allows bitmap drawing which is controlled using JavaScript (ie you draw on the <canvas> using JavaScript), and is what the RGraph libraries use to draw the charts. You could liken it to a piece of paper which is part of your page, on to which you can draw. Because you use JavaScript to draw on the canvas it becomes part of your page and allows interaction very easily.

The <canvas> tag uses a "fire and forget" drawing methodology - there is no DOM that is maintained, so if you want to alter something you'll probably (but not necessarily) have to redraw the entire canvas. The lack of a DOM means that canvas is fast to draw on and very responsive - important when you're providing interactive or animated charts to your users.

Other uses for <canvas> include providing a control panel to your users and using it to create games. You should note though that when it comes to accessibility then a more traditional HTML based interface that uses <canvas> for certain elements (eg charts!) may be preferable.

 

History of the canvas tag

HTML5 canvas was originally introduced by Apple in 2004 for use in Mac OS X WebKit to power dashboard applications and their Safari web browser. Since then it has been adopted by Mozilla and Opera and now the W3C has adopted it in the upcoming HTML5 specification. It's now supported by all modern web browsers including modern versions of MSIE (starting from version 9). In the case of MSIE7 and MSIE8 there is the ExCanvas library which adds support for the tag and is simply a matter of including an extra Javascript library in your page. This library (excanvas.js) is included in the RGraph download.

 

A usage example

[No canvas support]

The example to the right is a very simple example of drawing a few primitives on the canvas. The dotted border is provided by CSS to illustrate the drawing area. You use JavaScript to draw on the canvas and there is a wide range of drawing functions available to draw

The <canvas> tag itself is defined with just width, height and id attributes. The one here also has a style attribute to add the border. The HTML used is shown below.


<canvas id="cvs" width="600" height="250" style="border: 1px solid gray">[No canvas support]<canvas>

The content in between the tags is not shown if the browser supports canvas, and is if the browser doesn't. This provides for fallback content if the users browser doesn't support canvas.

<script>
    window.onload = function ()
    {
        // First get a reference to the canvas tag
        var canvas  = document.getElementById("cvs");
        
        // Now get a reference to the 2D drawing context (there is a 3D WebGL context
        // available - but its much more involved)
        var context = canvas.getContext('2d');
        
        
        // Set the fill color to red and draw the square
        context.fillStyle = 'red';
        context.fillRect(50,50,100,100);
        
        // Set the color to blue and draw a circle
        context.beginPath();
        context.fillStyle = 'blue';
        context.arc(250,150,50, 2 * Math.PI, false);
        context.fill();
    }
</script>

Here the onload event (you don't have to use the onload event unless you're using ExCanvas) draws two simple primitives - a square and a circle. Since the arc() function (used to draw a circle) is a "path" function a path is started using the beginPath() function, the circle is drawn and then the fill() function actually puts the arc on the canvas. There's a corresponding stroke() function if you also want to draw the outline.

 

Javascript & web charts

What makes the canvas tag so good for producing charts is the ability to interact seamlessly with both the user and the rest of the page. The charts that RGraph produces are all made from JavaScript so output from other JavaScript code can be used with ease. There's more information about charts made with JavaScript here and abundant examples across the whole RGraph website of RGraph charts interacting with JavaScript.

 

Canvas compared to SVG

HTML5 canvas can be compared in some ways to SVG - which is an older XML and vector based alternative for drawing in HTML pages. SVG is at a more abstract level than canvas and maintains a record of everything drawn, using a DOM. This is then converted to a bitmap when shown. In the above example, if the coordinates of the square are changed (eg in an animation), then the whole canvas needs to be cleared and redrawn for each frame of that animation. It is possible to get away with not clearing the enitire canvas - and only the relevant region - though this will require more in-depth planning and a significant amount of extra code.

As a result of not having to maintain a DOM though, canvas is very fast to draw on and display to the browser and as a result it can give yout page an air of speed.

 

Browser support

Modern browsers that support HTML5 also support canvas, including MSIE9+ (with MSIE9 you need to use the HTML5 doctype, but not from MSIE10). Earlier versions of MSIE have some support that you can make use of through compatibility layers provided by Google and Mozilla. One such library - ExCanvas - is provided in the RGraph archive allowing MSIE7 and MSIE8 to display the graphs (albeit without the dynamic features that modern browsers can make use of). You can read more about Microsoft Internet Explorer support here and there is a table of browsers that support HTML5 canvas on WikiPedia here. There's also more about browser support in the implementation documentation here.

 

The antialiasing issue

By default lines are anti-aliased - and this can make them appear thicker than what they should be and blurry. This can be avoided by offsetting your coordinates to the nearest half-pixel. Formerly, RGraph used a function (called AA() ) to handle the offsetting - however now the canvas is translate()ed in the constructor by half a pixel in both the X and Y directions and then coordinates are rounded to whole values using Math.round(). This is faster than working out the nearest half-pixel value in a user defined function. You can read more about this antialiasing fix and see an example here.

Keep in mind though - when you clear the canvas with the clearRect() function the transformation matrix is not altered. What this means is that the translate() you have done will still be in effect - so you don't need to translate the canvas again.

On the other hand if you clear the canvas by setting the width to itself - this in effect "resets" the canvas and clears any transformation that you have done. So you will have to translate again to keep your lines crisp and not blurry.

RGraph differentiates these actions as clearing the canvas and resetting the canvas. This makes it a bit more clear what the intended action of your code is - though in many cases the actions will make little difference. Sample functions are:

        function Reset(canvas)
        {
            canvas.width = canvas.width;
            
            // If you translate the canvas by half a pixel then the Reset() function would be a
            // good place to reset that flag
        }


        function Clear(canvas)
        {
            var context = canvas.getContext('2d');
            var width   = canvas.width;
            var height  = canvas.height;
            
            context.clearRect(0, 0, width, height);
        }