View the RGraph Facebook page View the RGraph Google+ page Share RGraph on Twitter Share RGraph on LinkedIn

Measuring text height with HTML5 canvas

Measuring the width of text in HTML5 canvas is a simple affair of using the context.measureText() method. This method however only provides the width of the text - not the height. Normally this isn't so bad - except when you absolutely need the height - it's not available. Fortunately this can be resolved by using the below function. This function takes the text, whether it's bold or not, the font and the point size (eg 12pt = 12) and adds it to a dynamically generated DIV that's positioned off screen. This DIV can then be measured using the offsetWidth and the offsetHeight and these measurements can then be used as the dimensions.

A point worthy of note is that adding elements to the DOM has a cost - and in some browsers this can slow down an animation. So for this reason the function uses a cache so that it doesn't repeatedly measure the same thing over and over again. This method of measuring the text height is used in RGraph to good effect when displaying multi-line text (eg this Horizontal Bar chart example).

/**
* Measures text by creating a DIV in the document and adding the relevant text to it.
* Then checking the .offsetWidth and .offsetHeight. Because adding elements to the DOM is not particularly
* efficient in animations (particularly) it caches the measured text width/height.
* 
* @param  string text   The text to measure
* @param  bool   bold   Whether the text is bold or not
* @param  string font   The font to use
* @param  size   number The size of the text (in pts)
* @return array         A two element array of the width and height of the text
*/
function MeasureText(text, bold, font, size)
{
    // This global variable is used to cache repeated calls with the same arguments
    var str = text + ':' + bold + ':' + font + ':' + size;
    if (typeof(__measuretext_cache__) == 'object' && __measuretext_cache__[str]) {
        return __measuretext_cache__[str];
    }

    var div = document.createElement('DIV');
        div.innerHTML = text;
        div.style.position = 'absolute';
        div.style.top = '-100px';
        div.style.left = '-100px';
        div.style.fontFamily = font;
        div.style.fontWeight = bold ? 'bold' : 'normal';
        div.style.fontSize = size + 'pt';
    document.body.appendChild(div);
    
    var size = [div.offsetWidth, div.offsetHeight];

    document.body.removeChild(div);
    
    // Add the sizes to the cache as adding DOM elements is costly and can cause slow downs
    if (typeof(__measuretext_cache__) != 'object') {
        __measuretext_cache__ = [];
    }
    __measuretext_cache__[str] = size;
    
    return size;
}