Max
Max

Reputation: 1131

Calculate letter size in javascript

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?

Upvotes: 4

Views: 2398

Answers (2)

danvk
danvk

Reputation: 16905

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.

Upvotes: 4

Irongaze.com
Irongaze.com

Reputation: 1646

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?

Upvotes: 4

Related Questions