Measuring text height with the canvas tag
Written by Richard Heyes, RGraph author, on 14th January 2013
Measuring the width of text 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.
//
// Measures text by creating a cdiv
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;
}