Обчислити ширину тексту за допомогою JavaScript


466

Я хотів би використовувати JavaScript для обчислення ширини рядка. Чи можливо це без використання моноспейкового шрифту?

Якщо це не вбудований, моя єдина ідея - створити таблицю ширини для кожного символу, але це досить необґрунтовано, особливо підтримуючи Unicode та різні типи розмірів (і всі браузери з цього приводу).


10
Не забудьте, що якщо ви використовуєте зовнішні шрифти, вам доведеться користуватися наведеними нижче методами після їх завантаження. Ви можете не усвідомлювати цього, якщо у вас є кеш-пам'ять або якщо встановлені локальні версії.
Сет У. Кляйн

Відповіді:


355

Створіть стиль 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>


8
Єдине, що я хочу додати, це те, що це може дати неправильні розміри залежно від того, які стилі використовуються. Пам'ятайте, що у вас можуть бути такі стилі, як p {літерний інтервал: 0,1ем; } що елемент DIV не відображатиметься. Ви повинні переконатися, що наявні стилі відповідають тому, де ви будете використовувати текст.
Джим

5
Коментар Дітто Джима - двічі перевірте, щоб переконатися, що контейнер, div в цьому випадку, не має інших стилів, застосованих до нього за допомогою правил вибору css, про які ви, можливо, не знаєте на той час. Скріпіть усі відповідні стилі з контейнера, перш ніж застосовувати ті, які вам важливі, перш ніж вимірювати.
Джейсон Бантінг

44
Також слід помістити пробіл: тепер, якщо ви думаєте, що текст перевищить ширину браузера.
Herb Caudill

5
@BBog все, що хапає навколо, чому я пропоную інший, менш хакітний, підхід вниз. Подивіться це тут .
Домі

11
Просто цікаво, для чого потрібен +1кожен вимір?
Кіп

385

У 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 /programming/118241/calculate-text-width-with-javascript/21015393#21015393
 */
function getTextWidth(text, font) {
    // re-use canvas object for better performance
    var canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
    var context = canvas.getContext("2d");
    context.font = font;
    var metrics = context.measureText(text);
    return metrics.width;
}

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

Ця скрипка порівнює цей метод Canvas з варіантом методу на основі DOM на основі Боба Монтеверде , щоб ви могли проаналізувати та порівняти точність результатів.

У цьому підході є кілька переваг, серед яких:

ПРИМІТКА. Коли ви додаєте текст у свій DOM, не забудьте також врахувати прокладку, поле та межу .

ПРИМІТКА 2. У деяких браузерах цей метод дає точність субпікселя (результат - число з плаваючою комою), в інших - ні (результат - лише цілий). Ви можете запустити Math.floor(або Math.ceil) на результат, щоб уникнути невідповідностей. Оскільки метод на основі DOM ніколи не є точним для пікселів, цей метод має навіть більш високу точність, ніж інші методи.

Відповідно до цього jsperf (завдяки коментарям у коментарях), метод Canvas та метод на основі DOM приблизно однаково швидкі, якщо кешування додано до методу на основі DOM, і ви не використовуєте Firefox. У Firefox чомусь цей Canvas метод набагато швидше, ніж метод на основі DOM (станом на вересень 2014 року).


7
Це приголомшливий варіант, я про це не знав. Коли-небудь порівнювати показники цього показника з результатами вимірювань у DOM?
SimplGy

2
Я додав кешування до цього показника jsperf. Зараз два способи майже нарівні: jsperf.com/measure-text-width/4
Брендон Блум

1
@Martin Так? Що стосується "багатьох елементів HTML" тут? Об'єкт полотна в цьому прикладі навіть не приєднаний до DOM. І навіть окрім цього, зміна шрифту в контексті малювання полотна навіть не впливає на полотно, поки ви strokeText()або fillText(). Можливо, ви мали намір прокоментувати іншу відповідь?
Ajedi32

1
Приємне рішення. Я обернув кілька інших методів навколо відповіді Домі, щоб я міг - отримати (потенційно) усічену рядок з еліпсисом (...) наприкінці, якщо вона не поміститься в заданому просторі (стільки ж рядка як можна буде використовуватись) - Передайте елемент JQuery, який повинен містити (можливо, усічений) рядок, та визначайте атрибути шрифту динамічно, щоб їх не потрібно було жорстко закодувати, дозволяючи атрибутам шрифту CSS змінюватись без порушення макет. JSFiddle Here: jsfiddle.net/brebey/1q94gLsu/6/embed
BRebey

2
Добре, що користувач цього не бачить!
clabe45

110

Ось один я зібрав разом без прикладу. Схоже, ми всі на одній сторінці.

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()

** Додано white-space: nowrapтак, що рядки шириною більше, ніж ширина вікна, можна обчислити.


2
Дякую JordanC. Я хотів би додати одне, якщо ви багато разів телефонуєте на одній сторінці, а продуктивність - це проблема, ви можете зберегти DIV і просто змінити вміст і перевірити ширину. Я просто зробив це так, як тільки все було сказано і зроблено, DOM буде таким же, як і коли ви починали
Боб Монтеверде

3
Я не став би додавати цей метод, Stringоскільки він зменшує проблематику вашої програми (окремий основний код проти коду інтерфейсу). Уявіть, що ви хочете перенести свій основний код на платформу з дуже іншим фреймворком інтерфейсу ...
Домі

23
Це поганий дизайн , він не тільки поєднує вашу модель з вашим поглядом, але і з'єднує її безпосередньо з jQuery. Крім того, це пекло переповнення, це, безумовно, не добре.
Джеймс

1
Якщо ви хочете значення float, ви можете використовувати, o[0].getBoundingClientRect().widthяк тут запропоновано: stackoverflow.com/a/16072668/936397
Alexander Olsson

1
@virus добре сказала, що 100+ людей, мабуть, не дбають про продуктивність ... Тим не менш, це не робить те, що я сказав, менш валідним або правдивим.
Джеймс

30

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);

26

Це працює для мене ...

// Handy JavaScript to measure the size taken to render the supplied text;
// you can supply additional style information too if you have it.

function measureText(pText, pFontSize, pStyle) {
    var lDiv = document.createElement('div');

    document.body.appendChild(lDiv);

    if (pStyle != null) {
        lDiv.style = pStyle;
    }
    lDiv.style.fontSize = "" + pFontSize + "px";
    lDiv.style.position = "absolute";
    lDiv.style.left = -1000;
    lDiv.style.top = -1000;

    lDiv.innerHTML = pText;

    var lResult = {
        width: lDiv.clientWidth,
        height: lDiv.clientHeight
    };

    document.body.removeChild(lDiv);
    lDiv = null;

    return lResult;
}

Привіт, ваша відповідь справді корисна, проте використовуйте .cssText замість .style для підтримки IE 8 і нижче ..
Діліп Раджкумар

Ця відповідь чудова, але коли я генерую великий фрагмент тексту, він стає неточним на кілька пікселів. Це тому, що ширина не ціле число?
Бобтроопо

20

У бібліотеці JavaScript ExtJS є чудовий клас під назвою Ext.util.TextMetrics, який "забезпечує точні вимірювання пікселів для блоків тексту, щоб ви могли точно визначити, наскільки високим і широким у пікселях буде даний блок тексту". Ви можете або скористатися ним безпосередньо, або переглянути його джерело для коду, щоб побачити, як це робиться.

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


1
ExtJS має дивну ліцензію. Або ви платите поточним обслуговуючим особам, Компанія Sencha, щоб ними користуватися, або ви повинні відкрити всі пов'язані з кодом у вашій програмі. Це шоу-пробка для більшості компаній. jQuery, з іншого боку, використовує високодозволену ліцензію MIT.
девданке

1
Чи не JavaScript автоматично відповідає вимогам відкритого коду? Ви подаєте джерело кожному, хто переглядає сторінку.
PatrickO

10
Існує різниця між можливістю перегляду вихідного коду та відкритого коду, який визначається ліцензуванням.
Parker Ault

Дякуємо тим, хто з нас ще використовує ExtJS :-)
Monarch Wadia

1
ви повинні дозволити ExtJS відпочити у спокої
canbax

19

Мені подобається ваша "єдина ідея" просто робити статичну карту ширини символів! Насправді це добре працює в моїх цілях. Іноді, з міркувань продуктивності або через те, що у вас немає простого доступу до 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 і отримав обмежувальне поле та зберег його до цього масиву; більше коду та пояснення та демонстрації тут .


1
це розумне рішення, приємне :) Я завжди використовую один і той же шрифт / розмір, тому він мені добре підходить. Я вважав, що ефективність рішень DOM / Canvas є справжньою проблемою, це дійсно чисто, ура!
mikeapr4

1
усуває необхідність в полотно +1
Frage

Ви можете позбутися * fontSizeі просто скористатися ними
Метт Флетчер

Яка дивовижна відповідь!
almosnow


7

Ви можете використовувати полотно, щоб вам не довелося так сильно мати справу з властивостями css:

var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
ctx.font = "20pt Arial";  // This can be set programmaticly from the element's font-style if desired
var textWidth = ctx.measureText($("#myElement").text()).width;

Хіба це не набагато більш важка вага (з отриманням 2d контексту тощо), ніж створення елемента DOM і визначення для нього властивостей css?
Pharao2k

1
Це чистий підхід, якщо ви вже використовуєте полотно для чогось. Але ДУЖЕ ПОЛІ. Один виклик ukreText займає приблизно 8-10 мс (за допомогою Chrome).
Rui Marques

6
<span id="text">Text</span>

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

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


Це більш-менш важливі рішення для верхніх рішень, але оскільки ваш текст може бути розбитий на кілька рядків, вони додають до CSS декілька стилів CSS, щоб отримати реальну повну ширину тексту.
Адріан Мейр

2

Код-фрагменти нижче, "обчислюють" ширину 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
Спробуйте двійковий пошук замість зациклення 1 посимвольний: см мій коментар на відповідь Алекса на stackoverflow.com/questions/536814 / ...
StanleyH

@StanleyH: Гарна ідея - я реалізую вашу пропозицію якнайшвидше.
Течек

2

Краще в тому, щоб виявити, чи правильно підійде текст перед тим, як відобразити елемент. Таким чином, ви можете використовувати цю функцію, яка не вимагає, щоб елемент був на екрані.

function textWidth(text, fontProp) {
    var tag = document.createElement("div");
    tag.style.position = "absolute";
    tag.style.left = "-999em";
    tag.style.whiteSpace = "nowrap";
    tag.style.font = fontProp;
    tag.innerHTML = text;

    document.body.appendChild(tag);

    var result = tag.clientWidth;

    document.body.removeChild(tag);

    return result;
}

Використання:

if ( textWidth("Text", "bold 13px Verdana") > elementWidth) {
    ...
}

2

У випадку, якщо хтось ще потрапив сюди, шукаючи і спосіб виміряти ширину рядка, і спосіб дізнатися, який найбільший розмір шрифту, який буде відповідати певній ширині, ось функція, що ґрунтується на рішенні @ Domi за допомогою двійкового пошуку :

/**
 * Find the largest font size (in pixels) that allows the string to fit in the given width.
 * 
 * @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 ?px verdana") -- note the use of ? in place of the font size.
 * @param {width} the width in pixels the string must fit in
 * @param {minFontPx} the smallest acceptable font size in pixels
 * @param {maxFontPx} the largest acceptable font size in pixels
**/
function GetTextSizeForWidth( text, font, width, minFontPx, maxFontPx )
{
    for ( ; ; )
    {
        var s = font.replace( "?", maxFontPx );
        var w = GetTextWidth( text, s );
        if ( w <= width )
        {
            return maxFontPx;
        }

        var g = ( minFontPx + maxFontPx ) / 2;

        if ( Math.round( g ) == Math.round( minFontPx ) || Math.round( g ) == Math.round( maxFontPx ) )
        {
            return g;
        }

        s = font.replace( "?", g );
        w = GetTextWidth( text, s );
        if ( w >= width )
        {
            maxFontPx = g;
        }
        else
        {
            minFontPx = g;
        }
    }
}

Це працює чудово (у поєднанні з кодом з відповіді Домі)
r3wt

1

Спробуйте цей код:

function GetTextRectToPixels(obj)
{
var tmpRect = obj.getBoundingClientRect();
obj.style.width = "auto"; 
obj.style.height = "auto"; 
var Ret = obj.getBoundingClientRect(); 
obj.style.width = (tmpRect.right - tmpRect.left).toString() + "px";
obj.style.height = (tmpRect.bottom - tmpRect.top).toString() + "px"; 
return Ret;
}

1

Ширину та висоту тексту можна отримати за допомогою clientWidthтаclientHeight

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

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

переконайтеся, що для властивості положення стилю встановлено абсолютне значення

element.style.position = "absolute";

не обов'язково знаходитися всередині a div, може бути всередині a pчи aspan


1

Будівництво геть відповіді Діпак Надара в , я змінив функцію параметра, щоб прийняти текст і стилі шрифтів. Вам не потрібно посилатися на елемент. Крім того, вони fontOptionsмають за замовчуванням, тому вам не потрібно буде постачати їх усі.

(function($) {
  $.format = function(format) {
    return (function(format, args) {
      return format.replace(/{(\d+)}/g, function(val, pos) {
        return typeof args[pos] !== 'undefined' ? args[pos] : val;
      });
    }(format, [].slice.call(arguments, 1)));
  };
  $.measureText = function(html, fontOptions) {
    fontOptions = $.extend({
      fontSize: '1em',
      fontStyle: 'normal',
      fontWeight: 'normal',
      fontFamily: 'arial'
    }, fontOptions);
    var $el = $('<div>', {
      html: html,
      css: {
        position: 'absolute',
        left: -1000,
        top: -1000,
        display: 'none'
      }
    }).appendTo('body');
    $(fontOptions).each(function(index, option) {
      $el.css(option, fontOptions[option]);
    });
    var h = $el.outerHeight(), w = $el.outerWidth();
    $el.remove();
    return { height: h, width: w };
  };
}(jQuery));

var dimensions = $.measureText("Hello World!", { fontWeight: 'bold', fontFamily: 'arial' });

// Font Dimensions: 94px x 18px
$('body').append('<p>').text($.format('Font Dimensions: {0}px x {1}px', dimensions.width, dimensions.height));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>


0

Я думаю, це схоже на запис Depak, але засноване на роботі Луї Лазаріса, опублікованій у статті на сторінці вражаючих веб- сайтів

(function($){

        $.fn.autofit = function() {             

            var hiddenDiv = $(document.createElement('div')),
            content = null;

            hiddenDiv.css('display','none');

            $('body').append(hiddenDiv);

            $(this).bind('fit keyup keydown blur update focus',function () {
                content = $(this).val();

                content = content.replace(/\n/g, '<br>');
                hiddenDiv.html(content);

                $(this).css('width', hiddenDiv.width());

            });

            return this;

        };
    })(jQuery);

Подія fit використовується для виклику функції негайно після того, як функція буде пов'язана з керуванням.

наприклад: $ ('input'). autofit (). тригер ("fit");


0

Без 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);

при встановленні номера не працює, тому що простір не потрібен, якщо його видалити, він буде добре працювати: fontSize + "px arial" -> fontSize + "px arial", саме це.
Альберто Акунья

0

Загадка робочого прикладу: http://jsfiddle.net/tdpLdqpo/1/

HTML:

<h1 id="test1">
    How wide is this text?
</h1>
<div id="result1"></div>
<hr/>
<p id="test2">
    How wide is this text?
</p>
<div id="result2"></div>
<hr/>
<p id="test3">
    How wide is this text?<br/><br/>
    f sdfj f sdlfj lfj lsdk jflsjd fljsd flj sflj sldfj lsdfjlsdjkf sfjoifoewj flsdjfl jofjlgjdlsfjsdofjisdojfsdmfnnfoisjfoi  ojfo dsjfo jdsofjsodnfo sjfoj ifjjfoewj fofew jfos fojo foew jofj s f j
</p>
<div id="result3"></div>

JavaScript-код:

function getTextWidth(text, font) {
    var canvas = getTextWidth.canvas ||
        (getTextWidth.canvas = document.createElement("canvas"));
    var context = canvas.getContext("2d");
    context.font = font;
    var metrics = context.measureText(text);
    return metrics.width;
};

$("#result1")
.text("answer: " +
    getTextWidth(
             $("#test1").text(),
             $("#test1").css("font")) + " px");

$("#result2")
    .text("answer: " +
        getTextWidth(
             $("#test2").text(),
             $("#test2").css("font")) + " px");

$("#result3")
    .text("answer: " +
        getTextWidth(
             $("#test3").text(),
             $("#test3").css("font")) + " px");

0

Element.getClientRects()Метод повертає колекцію DOMRectоб'єктів , які вказують обмежують прямокутники для кожного прикордонного поле CSS в клієнті. Повернене значення - це сукупність DOMRectоб'єктів, по одному для кожного граничного вікна CSS, пов'язаного з елементом. Кожен DOMRectоб'єкт містить тільки для читання left, top, rightі bottomвластивості , що описують форму кордону, в пікселях, з лівого верхнього по відношенню до верхньої лівої частини вікна перегляду.

Element.getClientRects () від Mozilla Contributors ліцензується під CC-BY-SA 2.5 .

Підсумовування всіх повернених ширин прямокутника дає загальну ширину тексту в пікселях.

document.getElementById('in').addEventListener('input', function (event) {
    var span = document.getElementById('text-render')
    span.innerText = event.target.value
    var rects = span.getClientRects()
    var widthSum = 0
    for (var i = 0; i < rects.length; i++) {
        widthSum += rects[i].right - rects[i].left
    }
    document.getElementById('width-sum').value = widthSum
})
<p><textarea id='in'></textarea></p>
<p><span id='text-render'></span></p>
<p>Sum of all widths: <output id='width-sum'>0</output>px</p>


0

Я створив крихітний модуль ES6 (використовує jQuery):

import $ from 'jquery';

const $span=$('<span>');
$span.css({
    position: 'absolute',
    display: 'none'
}).appendTo('body');

export default function(str, css){
    $span[0].style = ''; // resetting the styles being previously set
    $span.text(str).css(css || {});
    return $span.innerWidth();
}

Простий у використанні:

import stringWidth from './string_width';
const w = stringWidth('1-3', {fontSize: 12, padding: 5});

Хороша річ, яку ви можете помітити - вона дозволяє враховувати будь-які атрибути CSS, навіть запаски!


0

Ви також можете це зробити за допомогою 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;
}

-1
var textWidth = (function (el) {
    el.style.position = 'absolute';
    el.style.top = '-1000px';
    document.body.appendChild(el);

    return function (text) {
        el.innerHTML = text;
        return el.clientWidth;
    };
})(document.createElement('div'));
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.