Espero que haya alguien que me ayude con esto: necesito obtener el tamaño exacto de un texto. Solo midiendo un lapso más o menos no es lo suficientemente preciso para mis propósitos.
En este momento, estoy usando un lienzo para encontrar los píxeles no transparentes en el lienzo. Este es mi código:
// 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>Esto funciona para obtener la altura exacta del texto, pero no el ancho. Así que uso "measureText" en este momento, pero esa función tiene diferentes tamaños según el navegador y la fuente que uso. Si uso una fuente regular, funciona bastante bien. Pero si uso una fuente más divertida, no funciona en absoluto.
Aquí hay un ejemplo:
https://i.imgur.com/ySOIbDR.png
La caja negra es el tamaño medido. Y como puede ver, "measureText" no obtiene el ancho correcto. En este momento no tengo idea de qué más podría hacer.
Ok, entonces lo acabo de hacer funcionar.
¿Qué estoy haciendo? Bueno, en mi caso, sé que el texto siempre comenzará en un valor x de 0. Por lo tanto, la longitud del texto es el píxel no transparente con el valor x más alto en la matriz dada por getImageData() . Así que estoy recorriendo getImageData() -array. Si encuentro un píxel que tiene un valor alfa mayor que 0, guardaré su valor xey en highestPixel . La próxima vez que encuentre un píxel, verificaré si su valor de x es mayor que el que se encuentra actualmente en highestPixel . Si es así, sobrescribiré el highestPixel más alto con los nuevos valores. Al final, devuelvo highestPixel y su valor x será la longitud exacta del texto.
Aquí está el código:
// 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>