使用 JavaScript 计算文本宽度

2022-08-29 22:59:28

我想使用JavaScript来计算字符串的宽度。这是否可能而不必使用等宽字体?

如果它不是内置的,我唯一的想法是为每个字符创建一个宽度表,但这是非常不合理的,特别是支持Unicode和不同的类型大小(以及所有浏览器)。


答案 1

HTML 5中,你可以只使用Canvas.measureText方法在这里进一步解释)。

试试这个小提琴

/**
  * Uses canvas.measureText to compute and return the width of the given text of given font in pixels.
  * 
  * @param {String} text The text to be rendered.
  * @param {String} font The css font descriptor that text is to be rendered with (e.g. "bold 14px verdana").
  * 
  * @see https://stackoverflow.com/questions/118241/calculate-text-width-with-javascript/21015393#21015393
  */
function getTextWidth(text, font) {
  // re-use canvas object for better performance
  const canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
  const context = canvas.getContext("2d");
  context.font = font;
  const metrics = context.measureText(text);
  return metrics.width;
}

function getCssStyle(element, prop) {
    return window.getComputedStyle(element, null).getPropertyValue(prop);
}

function getCanvasFont(el = document.body) {
  const fontWeight = getCssStyle(el, 'font-weight') || 'normal';
  const fontSize = getCssStyle(el, 'font-size') || '16px';
  const fontFamily = getCssStyle(el, 'font-family') || 'Times New Roman';
  
  return `${fontWeight} ${fontSize} ${fontFamily}`;
}

console.log(getTextWidth("hello there!", "bold 12pt arial"));  // close to 86

如果要使用某些特定元素的字体大小,则可以使用实用程序函数:myElgetCanvasFont

const fontSize = getTextWidth(text, getCanvasFont(myEl));
// do something with fontSize here...

说明: 该函数采用某些元素(默认情况下:'s)的字体,并将其转换为与 Context.font 属性兼容的格式。当然,任何元素在使用之前都必须首先添加到DOM中,否则它会给你虚假的值。getCanvasFontSizebody

更多注意事项

此方法有几个优点,包括:

  • 比其他(基于 DOM 的)方法更简洁、更安全,因为它不会更改全局状态,例如 DOM。
  • 通过修改更多画布文本属性(如 和 ),可以进行进一步的自定义。textAligntextBaseline

注意:将文本添加到 DOM 时,请记住还要考虑填充、边距和边框

注2:在某些浏览器上,此方法产生亚像素精度(结果是浮点数),而在其他浏览器上则不然(结果仅为整数)。您可能希望对结果运行(或),以避免不一致。由于基于DOM的方法从不具有亚像素精度,因此此方法的精度甚至高于此处的其他方法。Math.floorMath.ceil

根据这个jsperf(感谢评论中的贡献者),如果将缓存添加到基于DOM的方法并且您没有使用Firefox,则Canvas方法和基于DOM的方法的速度大致相同。在Firefox中,由于某种原因,这个Canvas方法基于DOM的方法快得多(截至2014年9月)。

性能

这个小提琴将此 Canvas 方法与 Bob Monteverde 基于 DOM 的方法的变体进行比较,因此您可以分析和比较结果的准确性。


答案 2

创建具有以下样式设置样式的 DIV。在 JavaScript 中,设置要尝试测量的字体大小和属性,将字符串放在 DIV 中,然后读取 DIV 的当前宽度和高度。它将拉伸以适合内容,并且大小将在字符串呈现大小的几个像素内。

var fontSize = 12;
var test = document.getElementById("Test");
test.style.fontSize = fontSize;
var height = (test.clientHeight + 1) + "px";
var width = (test.clientWidth + 1) + "px"

console.log(height, width);
#Test
{
    position: absolute;
    visibility: hidden;
    height: auto;
    width: auto;
    white-space: nowrap; /* Thanks to Herb Caudill comment */
}
<div id="Test">
    abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
</div>