Canvas has the measureText method of text to get the text information contained in the TextMetrics object. Through TextMetrics, we can directly obtain the width value of the text, but we cannot directly obtain the height value.
一、TextMetrics
TextMetrics.width read-only
Double type, the width of the inline string in CSS pixels. Based on current context font considerations.
TextMetrics.actualBoundingBoxLeft (en-US) read-only
double type, parallel to the baseline, the distance from the alignment point determined by the CanvasRenderingContext2D.textAlign property to the left side of the text rectangle boundary , calculated using CSS pixels; a positive value indicates that the left side of the text rectangle boundary is on the left side of the alignment point.
TextMetrics.actualBoundingBoxRight (en-US) read-only
double type, parallel to the baseline, the distance from the alignment point determined by the CanvasRenderingContext2D.textAlign property to the right side of the border of the text rectangle , calculated in CSS pixels.
TextMetrics.fontBoundingBoxAscent (en-US) 只读
Double type, the distance from the horizontal line indicated by the CanvasRenderingContext2D.textBaseline property to the top of the rectangle's highest border of all fonts used to render the text , calculated in CSS pixels.
TextMetrics.fontBoundingBoxDescent (en-US) 只读
Double type, the distance from the horizontal line indicated by the CanvasRenderingContext2D.textBaseline property to the bottommost rectangle boundary of all fonts used to render the text, calculated using CSS pixels.
TextMetrics.actualBoundingBoxAscent (en-US) read-only
Double type, the distance from the horizontal line indicated by the CanvasRenderingContext2D.textBaseline property to the top of the rectangle bounding the rendered text , calculated in CSS pixels.
TextMetrics.actualBoundingBoxDescent (en-US) read-only
Double type, the distance from the horizontal line indicated by the CanvasRenderingContext2D.textBaseline property to the bottom of the rectangle bounding the rendered text , calculated in CSS pixels.
Reference: https://developer.mozilla.org/zh-CN/docs/Web/API/TextMetrics
Second, calculate the width and height
<canvas id="canvas" width="550" height="500"></canvas>
1. Measure text width
When measuring the horizontal width of a piece of text, the sum of the sum may be larger than the width of the inline box ( ) due to slanted/italic letters that cause characters to be wider than their intended width actualBoundingBoxLeft
. actualBoundingBoxRight
width
So computing actualBoundingBoxLeft
the actualBoundingBoxRight
sum of the sum is a more accurate way to get the absolute width of the text:
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const text = "Abcdefghijklmnop";
ctx.font = "italic 50px serif";
const textMetrics = ctx.measureText(text);
console.log(textMetrics.width);
// 459.8833312988281
console.log(
textMetrics.actualBoundingBoxRight + textMetrics.actualBoundingBoxLeft,
);
// 462.8833333333333
2. Measure text height
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
const text = "Abcdefghijklmnop";
ctx.font = "italic 50px serif";
const textMetrics = ctx.measureText(text);
// 所有字在这个字体下的高度
let fontHeight = textMetrics.fontBoundingBoxAscent + textMetrics.fontBoundingBoxDescent;
// 当前文本字符串在这个字体下用的实际高度
let actualHeight = textMetrics.actualBoundingBoxAscent + textMetrics.actualBoundingBoxDescent;
3. Example application
1. Implement multi-line text in canvas
// canvas多行文本
; (function (global) {
"use strict";
/**
*
* @param {*} showStroke 是否显示描边
* @param {*} text 文本
* @param {*} x 中心点x坐标
* @param {*} y 中心点y坐标
* @param {*} maxWidth 最大宽度
* @param {*} lineHeight 行高
* @returns
*/
global.CanvasRenderingContext2D.prototype.wrapText = function (showStroke, text, x, y, maxWidth, lineHeight) {
if (typeof text != 'string' || typeof x != 'number' || typeof y != 'number') {
return;
}
var context = this;
var canvas = context.canvas;
if (typeof maxWidth == 'undefined') {
maxWidth = (canvas && canvas.width) || 300;
}
if (typeof lineHeight == 'undefined') {
lineHeight = (canvas && parseInt(window.getComputedStyle(canvas).lineHeight)) || parseInt(window.getComputedStyle(document.body).lineHeight);
}
// 字符分隔为数组
var arrText = text.split('');
var line = '';
for (let n = 0; n < arrText.length; n++) {
let testLine = line;
// 换行符
if(arrText[n] === '\n') {
showStroke && context.strokeText(line, x, y);
context.fillText(line, x, y);
line = '';
y += lineHeight; // 行高
} else {
testLine = line + arrText[n];
let metrics = context.measureText(testLine, context.font);
// 计算文本宽度
let testWidth = metrics.actualBoundingBoxRight + metrics.actualBoundingBoxLeft;
if (testWidth > maxWidth && n > 0) {
showStroke && context.strokeText(line, x, y);
context.fillText(line, x, y);
line = arrText[n];
y += lineHeight;
} else {
line = testLine;
}
}
}
showStroke && context.strokeText(line, x, y);
context.fillText(line, x, y);
};
})(window);
this.ctx.wrapText(true, '文本', 20, 20, 100, 20)
2. HTML tags calculate text width and height
Note: The minimum font size can only be 12px
/*
* html计算文本宽高
*/
; (function (global) {
"use strict";
global.TextNode = function () {
/**
*
* @param {*} text 文本
* @param {*} font 字体样式
* @param {*} width 标签宽度
* @param {*} height 标签高度
* @returns
*/
const _getTextWH = function (text, font, width, height) {
const $span = global.document.createElement("span");
$span.innerHTML = text
// const spanTextNode = global.document.createTextNode(text);
// $span.appendChild(spanTextNode);
$span.setAttribute("style", `font: ${font}; white-space: pre-wrap; position: fixed; top: 0; left: 0; display: block; line-height: 1; width: ${width ? width : 'auto'}; height: ${height ? height : 'auto'}`);
const $body = global.document.getElementsByTagName("body")[0];
$body.appendChild($span);
const spanRect = $span.getBoundingClientRect();
$body.removeChild($span);
// console.log(spanRect.width, spanRect.height)
return {
width: spanRect.width,
height: spanRect.height
}
}.bind(this);
let _txt = _getTextWH(...arguments);
// console.log('_txt', _txt)
return {
width: _txt.width,
height: _txt.height
};
};
})(window);
let _txt = TextNode('智能字幕', `${data.fontSize}px ${data.fontFamily}`)