I need to calculate the exact size of the letter in javascript. The letter can have different font-size or font-family attributes, etc.
I tried to use div element for this, but this method gives only the size of the div, not letter.
<div style="display: inline; background-color: yellow; font-size: 53px; line-height:32px">A</div>
Does anybody know how to solve this issue?
This is basically not possible for the general case. Font kerning will result in variable "widths" of letters depending on the operating system, browser, etc etc, and based on which letters are next to each other. Font substitution may happen if the os+browser don't have the font you specify.
Perhaps re-asking the question with the higher-level goal you're shooting for might result in proposed other approaches to your problem that might be more fruitful?
As others have mentioned, this isn't possible to measure directly. But you can get at it in a more roundabout way: draw the letter onto a canvas and determine which pixels are filled in.
Here's a demo that does this. The meat is this function:
/**
* Draws a letter in the given font to an off-screen canvas and returns its
* size as a {w, h, descenderH} object.
* Results are cached.
*/
function measureLetter(letter, fontStyle) {
var cacheKey = letter + ' ' + fontStyle;
var cache = measureLetter.cache;
if (!cache) {
measureLetter.cache = cache = {};
}
var v = cache[cacheKey];
if (v) return v;
// Create a reasonably large off-screen <canvas>
var cnv = document.createElement('canvas');
cnv.width = '200';
cnv.height = '200';
// Draw the letter
var ctx = cnv.getContext('2d');
ctx.fillStyle = 'black';
ctx.font = fontStyle;
ctx.fillText(letter, 0.5, 100.5);
// See which pixels have been filled
var px = ctx.getImageData(0, 0, 200, 200).data;
var minX = 200, minY = 200, maxX = 0, maxY = 0;
var nonZero = 0;
for (var x = 0; x < 200; x++) {
for (var y = 0; y < 200; y++) {
var i = 4 * (x + 200 * y);
var c = px[i] + px[i + 1] + px[i + 2] + px[i + 3];
if (c === 0) continue;
nonZero++;
minX = Math.min(x, minX);
minY = Math.min(y, minY);
maxX = Math.max(x, maxX);
maxY = Math.max(y, maxY);
}
}
var o = {w: maxX - minX, h: maxY - minY, descenderH: maxY - 100};
cache[cacheKey] = o;
return o;
}
Note that this is sensitive to antialiasing—the results might be off by a pixel.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With