Using normal text instead of canvas text for better looking text

Share RGraph:   To help my Google visibility (it can't get much worse!), if you like and use RGraph I'd appreciate it if you could link to me

Because native canvas text is not of the best quality RGraph now supports using accessible/DOM text instead of the native canvas API text functionality

Warning Not all features of RGraph are supported with accessible text (eg some 3D charts).
[No canvas support]

Being continually disappointed by the poor quality of the text that's rendered on a canvas, there's now an option to use accessible DOM text positioned over the canvas instead of native canvas rendered text.

The HTML5 canvas tag is a bitmap (not a vector) - and so the qauality of anything - including text - will degrade as you increase the zoom - in a similar way to how an image becomes blockier the more you zoom in.

Using accessible DOM text instead of native canvas text solves this issue - and text retains its quality regardless of the level of zoom. Try zooming this page (CTRL & + and CTRL & -) and you'll see.

    labels   = [];
    tooltips = [];
    data     = [];
    sales    = [
        ['Monday', 45],
    // Create the labels
    for (var i=0; i<sales.length; ++i) {
        data[i]     = sales[i][1];
        labels[i]   = sales[i][0];
        tooltips[i] = '{1}: {2}%'.format(labels[i], data[i]);

    new RGraph.Bar({
        id: 'cvs',
        data: data,
        options: {
            tooltips: labels,
            labels: labels,

            textAccessible: true,
            textAccessibleOverflow: true,
            textAccessiblePointerevents: true,

            textSize: 14,
            titleSize: 20,
            titleBold: true, // Default
            title: 'An example chart using accessible text',
            ymax: 100,
            colors: ['Gradient(#fcc:red:red)'],
            scaleZerostart: true,
            shadowOffsetx: 1,
            shadowOffsety: 1,
            shadowBlur: 5,
            gutterLeft: 5,
            gutterRight: 5,
            gutterTop: 50,
            gutterBottom: 5,
            unitsPost: '%',
            strokestyle: 'transparent',
            noaxes: true,
            backgroundGridVlines: false,
            backgroundGridBorder: false,
            clearto: 'white'

Caveats with accessible text

There are caveats-a-plenty with accessible text - mainly with interactive features. Things that aren't mentioned here may or may not work!

Adding your own event handlers

Being standard DOM nodes you can work with them as such. References to the <SPAN> tags are kept in the RGraph.text2.domNodeCache array. The first key in that array is the canvas ID and then you could use the for/in loop shown below to loop through the text nodes that pertain to that canvas tag. If you wanted to you could, in that loop, add them to a numerically indexed array, which you might then find easier to work with.

    // Loop through all of the accessible text nodes and add them to a one dimension,
    // numerically indexed array
    var texts = RGraph.text2.domNodeCache['cvs']; // Use the canvas ID here
    var arr   = new Array();

    for (var i in texts) {
    // This is an example of the sort of thing that you could then add
    arr[1].onmouseover = function (e)
    {         = '2px'; = 'red';          = '2px solid black';    = '5px';
    = function (e)
           = '';
   = '';
            = '';
      = '';
            = 'default';

    // And this is how to get the length of the text array
    var len = Object.keys(RGraph.text2.domNodeCache['cvs']).length;

Performance advantages with accessible text

Drawing text on canvas has, in the past, been called slow. Whether it still is is open to discussion. It most certainly won't be as fast though as simply not drawing text at all. And that is evident on the chart above in the smoothness of the animation.

By using accessible text that is essentially what is happening. If the DOM nodes were created and trashed for every frame of an animation then there would be no performance gain and a massive performance loss. But they're not.

The DOM text nodes are created and then the nodes are kept in the RGraph.text2.domNodeCache array. It's a cache so that the nodes aren't created over and over again. By doing this all of the text on the canvas is created once and reused for each frame of an animation. By repeatedly using the same text the text drawing part of the chart rendering is eliminated.

Accessibility advantages with accessible text

When it comes to accessibility with canvas - essentially it's an impenetrable black box. Anything drawn on it is unknown to the browser - much like an image. So by using accessible text you make the text as accessible as the other text on your page. The text can gain focus and can be read by screen readers just like normal text. It also responds to zoom operations like other text on your page.

Dealing with text that moves (in animation effects)

If you have text that moves in your chart - for example in an animated Bar chart or a Horizontal Bar chart when you have labelsAbove enabled - then this can slow down accessible text. This is because new DOM nodes need to be created for each bit of moving text on each frame of the animation. This can be worked around in some cases though by only enabling the text once the animation has completed. You can do this by using the animation-complete callback. The Bar chart and HBar chart both accommodate the labelsAbove text already. You accomplish the callback method like this:

.grow(null, function (obj)
    obj.set('labelsAbove', true);