Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

171
Vistas
Get exact size of text on a canvas in JavaScript

I hope there is someone out there to help me with this: I need to get the exact size of a text. Just measuring a span or so not precise enough for my purposes.

Right now, I am using a canvas to find the non-transparent pixels in the canvas. This is my code:

// a function to draw the text on the canvas

let text = "Hello World";
let canvas = document.getElementById('happy-canvas');
let width = 1000
let height = 100
canvas.width = width
canvas.height = height

let ctx = canvas.getContext('2d');
ctx.save();
ctx.font = "30px cursive";
ctx.clearRect(0, 0, width, height);
ctx.fillText(text, 0, 60);

  // get the image data
  let data = ctx.getImageData(0, 0, width, height).data,
    first = false,
    last = false,
    r = height,
    c = 0

  // get the width of the text and convert it to an integer
  const canvWidth = parseInt(ctx.measureText(text).width)

  //Find the last line with a non-transparent pixel
  while (!last && r) {
    r--
    for (c = 0; c < width; c++) {
      if (data[r * width * 4 + c * 4 + 3]) {
        last = r
        break
      }
    }
  }

  let canvasHeight = 0
  // Find the first line with a non-transparent pixel
  while (r) {
    r--
    for (c = 0; c < width; c++) {
      if (data[r * width * 4 + c * 4 + 3]) {
        first = r
        break
      }
    }

    canvasHeight = last - first
  }

  //draw a rectangle around the text
  ctx.strokeRect(0, first, canvWidth, canvasHeight)
<div> The last "d" is not completely inside of the the box
  <canvas id="happy-canvas" width="150" height="150"> I wonder what is here</canvas>
</div>

This works to get the exact height of the text, but not the width. So I use "measureText" right now, but that function gets different sizes depending on the browser and on the font I use. If I use a reagular font, it works quite well. But if I use a more playful font, it does not work at all.

Here is an example:

https://i.imgur.com/ySOIbDR.png

The black box is the measured size. And as you can see "measureText" does not get the correct width. Right now I am out of any idea, what else I could do.

about 4 years ago · Juan Pablo Isaza
1 Respuestas
Responde la pregunta

0

Ok, so I just got it working.

What am I doing? Well, in my case I know, that the text will always start at a x-value of 0. The length of the text is therefore the non-transparent pixel with the highest x-value in the array given by getImageData(). So I am looping through the getImageData()-array. If I find a pixel that has a higher alpha-value than 0, I will save its x and y value into highestPixel. The next time I find a pixel, I will check if its x-value is higher as the one that is currently in highestPixel. If so, I will overwrite highestPixel with the new values. At the end, I return highestPixel and its x-value will be the exact length of the text.

Here is the code:

// a function to draw the text on the canvas

let text = "Hello World";
let canvas = document.getElementById('happy-canvas');
let width = 1000
let height = 100
canvas.width = width
canvas.height = height

let ctx = canvas.getContext('2d');
ctx.save();
ctx.font = "30px cursive";
ctx.clearRect(0, 0, width, height);
ctx.fillText(text, 0, 60);

// get the image data
let data = ctx.getImageData(0, 0, width, height).data,
  first = false,
  last = false,
  r = height,
  c = 0

// get the width of the text and convert it to an integer
let getPixelwithHighestX = () => {
  let xOfPixel = 0
  let yOfPixel = 0
  let highestPixel = {
    x: 0,
    y: 0
  }
  for (let i = 3; i < data.length; i += 4) {
    if (data[i] !== 0) {
      yOfPixel = Math.floor(i / 4 / width)
      xOfPixel = Math.floor(i / 4) - yOfPixel * width
      if (xOfPixel > highestPixel.x) {
        highestPixel.x = xOfPixel
        highestPixel.y = yOfPixel
      }
    }
  }
  return highestPixel
}

let hightestPixel = getPixelwithHighestX()

//Find the last line with a non-transparent pixel
while (!last && r) {
  r--
  for (c = 0; c < width; c++) {
    if (data[r * width * 4 + c * 4 + 3]) {
      last = r
      break
    }
  }
}

let canvasHeight = 0
// Find the first line with a non-transparent pixel
while (r) {
  r--
  for (c = 0; c < width; c++) {
    if (data[r * width * 4 + c * 4 + 3]) {
      first = r
      break
    }
  }

  canvasHeight = last - first
}

//draw a rectangle around the text
ctx.strokeRect(0, first, hightestPixel.x, canvasHeight)
<div> The text is now completely inside the box
  <canvas id="happy-canvas" width="150" height="150"> I wonder what is here</canvas>
</div>

about 4 years ago · Juan Pablo Isaza Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda