获取 JavaScript 中 canvas 上文本的确切大小
Get exact size of text on a canvas in JavaScript
我希望有人能帮我解决这个问题:
我需要获得文本的确切大小。只是测量一个跨度左右,对我的目的来说不够精确。
现在,我正在使用 canvas 来查找 canvas 中的非透明像素。
这是我的代码:
// 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>
这可以获取文本的确切高度,但不能获取文本的宽度。
所以我现在使用“measureText”,但该函数会根据浏览器和我使用的字体获得不同的大小。
如果我使用常规字体,效果会很好。但是,如果我使用更有趣的字体,它根本不起作用。
这是一个例子:
https://i.imgur.com/ySOIbDR.png
黑框为实测尺寸。正如您所看到的,“measureText”没有获得正确的宽度。
现在我不知道我还能做什么。
好的,我刚开始工作。
我在做什么?
好吧,就我而言,我知道,文本将始终从 x-value 0 开始。
因此,文本的长度是 non-transparent 像素,在 getImageData()
给出的数组中具有最高 x-value 的像素。
所以我循环遍历 getImageData()
数组。如果我找到一个 alpha-value 大于 0 的像素,我会将其 x 和 y 值保存到 highestPixel
中。下次我找到一个像素时,我会检查它的 x-value 是否比当前 highestPixel
中的像素高。如果是这样,我将用新值覆盖 highestPixel
。最后,我 return highestPixel
和它的 x-value 将是文本的确切长度。
代码如下:
// 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>
我希望有人能帮我解决这个问题: 我需要获得文本的确切大小。只是测量一个跨度左右,对我的目的来说不够精确。
现在,我正在使用 canvas 来查找 canvas 中的非透明像素。 这是我的代码:
// 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>
这可以获取文本的确切高度,但不能获取文本的宽度。 所以我现在使用“measureText”,但该函数会根据浏览器和我使用的字体获得不同的大小。 如果我使用常规字体,效果会很好。但是,如果我使用更有趣的字体,它根本不起作用。
这是一个例子:
https://i.imgur.com/ySOIbDR.png
黑框为实测尺寸。正如您所看到的,“measureText”没有获得正确的宽度。 现在我不知道我还能做什么。
好的,我刚开始工作。
我在做什么?
好吧,就我而言,我知道,文本将始终从 x-value 0 开始。
因此,文本的长度是 non-transparent 像素,在 getImageData()
给出的数组中具有最高 x-value 的像素。
所以我循环遍历 getImageData()
数组。如果我找到一个 alpha-value 大于 0 的像素,我会将其 x 和 y 值保存到 highestPixel
中。下次我找到一个像素时,我会检查它的 x-value 是否比当前 highestPixel
中的像素高。如果是这样,我将用新值覆盖 highestPixel
。最后,我 return highestPixel
和它的 x-value 将是文本的确切长度。
代码如下:
// 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>