Рассчитать ширину текста с помощью JavaScript

Вот немного polyfill, который использует document.CurrentScript, если он существует, и возвращается к поиску скрипта по идентификатору.

<script id="uniqueScriptId">
    (function () {
        var thisScript = document.CurrentScript || document.getElementByID('uniqueScriptId');

        // your code referencing thisScript here
    ());
</script>

Если вы включите это в начало каждого тега скрипта, я верю вы сможете точно знать, какой скриптовый тег уволен, и вы также сможете ссылаться на тег сценария в контексте асинхронного обратного вызова.

Не проиндексирован, поэтому оставляйте отзыв для других, если вы пытаетесь это сделать.

420
задан Peter Mortensen 3 February 2016 в 13:31
поделиться

7 ответов

Создайте 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>
330
ответ дан Luca Kiebel 3 February 2016 в 13:31
поделиться

Без jQuery:

String.prototype.width = function (fontSize) {
    var el,
        f = fontSize + " px arial" || '12px arial';
    el = document.createElement('div');
    el.style.position = 'absolute';
    el.style.float = "left";
    el.style.whiteSpace = 'nowrap';
    el.style.visibility = 'hidden';
    el.style.font = f;
    el.innerHTML = this;
    el = document.body.appendChild(el);
    w = el.offsetWidth;
    el.parentNode.removeChild(el);
    return w;
}

// Usage
"MyString".width(12);
0
ответ дан Peter Mortensen 3 February 2016 в 13:31
поделиться
<span id="text">Text</span>

<script>
var textWidth = document.getElementById("text").offsetWidth;
</script>

Это должно работать пока < span> тег не имеет никаких других стилей, относился к нему. offsetWidth будет включать ширину любых границ, горизонтального дополнения, вертикальной ширины полосы прокрутки, и т.д.

4
ответ дан Bryan Friedman 3 February 2016 в 13:31
поделиться

Мне нравится твоя "единственная идея" просто сделать статическую карту ширины символов! Это на самом деле хорошо работает для моих целей. Иногда по соображениям производительности или из-за того, что у вас нет простого доступа к DOM, вам может понадобиться быстрый взломанный автономный калькулятор, откалиброванный для одного шрифта. Итак, вот один, откалиброванный для Helvetica; передать строку и (необязательно) размер шрифта:

function measureText(str, fontSize = 10) {
  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
  return str
    .split('')
    .map(c => c.charCodeAt(0) < widths.length ? widths[c.charCodeAt(0)] : avg)
    .reduce((cur, acc) => acc + cur) * fontSize
}

Этот гигантский уродливый массив представляет собой ширину символов ASCII, проиндексированную кодом символов. Так что это просто поддерживает ASCII (в противном случае предполагается средняя ширина символов). К счастью, ширина в основном линейно масштабируется в зависимости от размера шрифта, поэтому она отлично работает при любом размере шрифта. Ему явно не хватает понимания кернинга, лигатур или чего-то еще.

Чтобы «откалибровать», я просто рендерил каждый символ до charCode 126 (могущественная тильда) в SVG, получил ограничивающий прямоугольник и сохранил его в этом массиве; больше кода и объяснения и демо здесь .

10
ответ дан Toph 3 February 2016 в 13:31
поделиться

библиотека ExtJS javascript имеет большой класс по имени Ext.util. TextMetrics, который "обеспечивает точные пиксельные измерения для блоков текста так, чтобы можно было определить точно, насколько высокий и широкий, в пикселях, данный блок текста будет". Можно или использовать его непосредственно или просмотреть его источник для кодирования, чтобы видеть, как это сделано.

http://docs.sencha.com/extjs/6.5.3/modern/Ext.util.TextMetrics.html

19
ответ дан Andrew Myers 3 February 2016 в 13:31
поделиться

jQuery:

(function($) {

 $.textMetrics = function(el) {

  var h = 0, w = 0;

  var div = document.createElement('div');
  document.body.appendChild(div);
  $(div).css({
   position: 'absolute',
   left: -1000,
   top: -1000,
   display: 'none'
  });

  $(div).html($(el).html());
  var styles = ['font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing'];
  $(styles).each(function() {
   var s = this.toString();
   $(div).css(s, $(el).css(s));
  });

  h = $(div).outerHeight();
  w = $(div).outerWidth();

  $(div).remove();

  var ret = {
   height: h,
   width: w
  };

  return ret;
 }

})(jQuery);
30
ответ дан 22 November 2019 в 23:14
поделиться

Приведенные ниже фрагменты кода "вычисляют" ширину тега span, добавляют к нему "...", если он слишком длинный, и сокращают длину текста, пока он не умещается в его родительский элемент (или пока он не попробует более тысячи раз)

CSS

div.places {
  width : 100px;
}
div.places span {
  white-space:nowrap;
  overflow:hidden;
}

HTML

<div class="places">
  <span>This is my house</span>
</div>
<div class="places">
  <span>And my house are your house</span>
</div>
<div class="places">
  <span>This placename is most certainly too wide to fit</span>
</div>

JavaScript (с jQuery)

// loops elements classed "places" and checks if their child "span" is too long to fit
$(".places").each(function (index, item) {
    var obj = $(item).find("span");
    if (obj.length) {
        var placename = $(obj).text();
        if ($(obj).width() > $(item).width() && placename.trim().length > 0) {
            var limit = 0;
            do {
                limit++;
                                    placename = placename.substring(0, placename.length - 1);
                                    $(obj).text(placename + "...");
            } while ($(obj).width() > $(item).width() && limit < 1000)
        }
    }
});
2
ответ дан 22 November 2019 в 23:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: