我想使用JavaScript来计算字符串的宽度。如果不使用单行字体,这可能吗?

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


当前回答

文本的宽度和高度可以通过clientWidth和clienttheight获得

var element = document.getElementById ("mytext");

var width = element.clientWidth;
var height = element.clientHeight;

确保style position属性被设置为absolute

element.style.position = "absolute";

不需要在div中,可以在p或span中

其他回答

我为此写了一个小工具。也许对某些人有用。它不需要jQuery也能工作。

https://github.com/schickling/calculate-size

用法:

var size = calculateSize("Hello world!", {
   font: 'Arial',
   fontSize: '12px'
});

console.log(size.width); // 65
console.log(size.height); // 14

小提琴:http://jsfiddle.net/PEvL8/

从头重写了我的答案(谢谢你的减分)。 现在函数接受一个文本和css规则被应用(不再使用jQuery)。所以它也会尊重填充。结果值被四舍五入(您可以看到Math。四舍五入,如果你想要更精确的值,可以去掉)

function getSpan(){ const span = document.createElement('span') span.style.position = 'fixed'; span.style.visibility = 'hidden'; document.body.appendChild(span); return span; } function textWidth(str, css) { const span = getSpan(); Object.assign(span.style, css || {}); span.innerText = str; const w = Math.round(span.getBoundingClientRect().width); span.remove(); return w; } const testStyles = [ {fontSize: '10px'}, {fontSize: '12px'}, {fontSize: '60px'}, {fontSize: '120px'}, {fontSize: '120px', padding: '10px'}, {fontSize: '120px', fontFamily: 'arial'}, {fontSize: '120px', fontFamily: 'tahoma'}, {fontSize: '120px', fontFamily: 'tahoma', padding: '5px'}, ]; const ul = document.getElementById('output'); testStyles.forEach(style => { const li = document.createElement('li'); li.innerText = `${JSON.stringify(style)} > ${textWidth('abc', style)}`; ul.appendChild(li); }); <ul id="output"></ul>

你也可以使用createRange,这比文本克隆技术更准确:

function getNodeTextWidth(nodeWithText) {
    var textNode = $(nodeWithText).contents().filter(function () {
        return this.nodeType == Node.TEXT_NODE;
    })[0];
    var range = document.createRange();
    range.selectNode(textNode);
    return range.getBoundingClientRect().width;
}

这是我随手拼凑的一个例子。看来我们都达成共识了。

String.prototype.width = function(font) {
  var f = font || '12px arial',
      o = $('<div></div>')
            .text(this)
            .css({'position': 'absolute', 'float': 'left', 'white-space': 'nowrap', 'visibility': 'hidden', 'font': f})
            .appendTo($('body')),
      w = o.width();

  o.remove();

  return w;
}

使用它很简单:"a string".width()

**增加了空格:nowrap,因此宽度大于窗口宽度的字符串可以被计算。

我喜欢你的“唯一的想法”只是做一个静态字符宽度地图!它实际上很适合我的目的。有时,出于性能原因,或者因为不容易访问DOM,您可能只想要一个快速的、独立的、校准为单一字体的计算器。这是一个用Helvetica字体校准的;传递一个字符串和字体大小:

const widths = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2796875,0.2765625,0.3546875,0.5546875,0.5546875,0.8890625,0.665625,0.190625,0.3328125,0.3328125,0.3890625,0.5828125,0.2765625,0.3328125,0.2765625,0.3015625,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.2765625,0.2765625,0.584375,0.5828125,0.584375,0.5546875,1.0140625,0.665625,0.665625,0.721875,0.721875,0.665625,0.609375,0.7765625,0.721875,0.2765625,0.5,0.665625,0.5546875,0.8328125,0.721875,0.7765625,0.665625,0.7765625,0.721875,0.665625,0.609375,0.721875,0.665625,0.94375,0.665625,0.665625,0.609375,0.2765625,0.3546875,0.2765625,0.4765625,0.5546875,0.3328125,0.5546875,0.5546875,0.5,0.5546875,0.5546875,0.2765625,0.5546875,0.5546875,0.221875,0.240625,0.5,0.221875,0.8328125,0.5546875,0.5546875,0.5546875,0.5546875,0.3328125,0.5,0.2765625,0.5546875,0.5,0.721875,0.5,0.5,0.5,0.3546875,0.259375,0.353125,0.5890625]
const avg = 0.5279276315789471

function measureText(str, fontSize) {
  return Array.from(str).reduce(
    (acc, cur) => acc + (widths[cur.charCodeAt(0)] ?? avg), 0
  ) * fontSize
}

这个巨大的丑陋数组是由字符代码索引的ASCII字符宽度。所以这只支持ASCII(否则它假设平均字符宽度)。幸运的是,宽度基本上是随字体大小线性缩放的,所以它在任何字体大小下都能很好地工作。它明显缺乏对字距或结扎之类的意识。

为了“校准”,我只是在svg上渲染了charCode 126(强大的波浪号)的每个字符,并获得了边界框并将其保存到这个数组中;这里有更多的代码、解释和演示。