Oblicz szerokość tekstu za pomocą JavaScript

466

Chciałbym użyć JavaScript do obliczenia szerokości łańcucha. Czy jest to możliwe bez konieczności używania kroju pisma monospace?

Jeśli nie jest wbudowany, moim jedynym pomysłem jest utworzenie tabeli szerokości dla każdego znaku, ale jest to dość nierozsądne, szczególnie obsługując Unicode i różne rozmiary typów (i wszystkie przeglądarki w tym zakresie).

Jakub
źródło
10
Uwaga: jeśli używasz czcionek zewnętrznych, po ich załadowaniu będziesz musiał skorzystać z poniższych technik. Możesz nie zdawać sobie z tego sprawy, jeśli masz je w pamięci podręcznej lub masz zainstalowane wersje lokalne.
Seth W. Klein,

Odpowiedzi:

355

Utwórz DIV w stylu z następującymi stylami. W swoim JavaScript ustaw rozmiar czcionki i atrybuty, które próbujesz zmierzyć, umieść swój ciąg w DIV, a następnie przeczytaj aktualną szerokość i wysokość DIV. Rozciągnie się, aby dopasować do zawartości, a rozmiar będzie mieścić się w odległości kilku pikseli od renderowanego rozmiaru ciągu.

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>

CMPalmer
źródło
8
Dodam tylko, że może to dać niewłaściwe wymiary w zależności od używanych stylów. Pamiętaj, że możesz mieć style takie jak p {odstęp między literami: 0,1 em; } element DIV nie odzwierciedlałby. Musisz upewnić się, że stosowane style są odpowiednie dla miejsca, w którym będziesz używać tekstu.
Jim
5
Komentarz Ditto Jima - sprawdź dwukrotnie, aby upewnić się, że kontener, w tym przypadku div, nie ma żadnych innych stylów zastosowanych do niego za pomocą reguł wyboru css, o których możesz nie wiedzieć. Usuń wszystkie odpowiednie style z pojemnika przed zastosowaniem tych, na których Ci zależy przed pomiarem.
Jason Bunting,
44
Powinieneś także wstawić białe znaki: teraz, jeśli uważasz, że tekst przekroczy szerokość przeglądarki.
Herb Caudill,
5
@BBog cały ten hackowanie jest powodem, dla którego sugeruję inne, mniej hackerskie podejście na dole. Spójrz na to tutaj .
Domi
11
Ciekawe, po co +1jest ten wymiar?
Kip
385

W HTML 5 możesz po prostu użyć metody Canvas.measureText (dalsze wyjaśnienie tutaj ).

Wypróbuj to skrzypce :

/**
 * 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

To skrzypce porównuje tę metodę Canvas z odmianą metody opartej na modelu DOM Boba Monteverde'a , dzięki czemu można analizować i porównywać dokładność wyników.

Podejście to ma kilka zalet, w tym:

UWAGA: Kiedy dodajesz tekst do DOM, pamiętaj, aby wziąć również pod uwagę wypełnienie, margines i ramkę .

UWAGA 2: W niektórych przeglądarkach ta metoda zapewnia dokładność subpikseli (wynik jest liczbą zmiennoprzecinkową), w innych nie (wynik jest tylko liczbą całkowitą). Możesz uruchomić Math.floor(lub Math.ceil) wynik, aby uniknąć niespójności. Ponieważ metoda oparta na DOM nigdy nie jest dokładna w subpikselach, ta metoda ma jeszcze wyższą precyzję niż inne metody tutaj.

Zgodnie z tym jsperf (dzięki autorom komentarzy) metoda Canvas i metoda DOM są równie szybkie, jeśli buforowanie jest dodawane do metody DOM i nie używasz przeglądarki Firefox. W Firefoksie z jakiegoś powodu ta metoda Canvas jest znacznie szybsza niż metoda oparta na DOM (stan na wrzesień 2014 r.).

Domi
źródło
7
To niesamowita opcja, nie wiedziałem o tym. Czy kiedykolwiek porównywałeś wydajność tego do pomiaru w DOM?
SimplGy
2
Dodałem buforowanie do tego testu porównawczego jsperf. Teraz te dwie metody są prawie na równi: jsperf.com/measure-text-width/4
Brandon Bloom
1
@Martin Huh? Co „wiele elementów HTML” ma z tym wspólnego? Obiekt canvas w tym przykładzie nie jest nawet dołączony do DOM. A poza tym zmiana czcionki w kontekście rysowania na płótnie w ogóle nie wpływa na płótno, dopóki ty strokeText()lub ty fillText(). Może chciałeś skomentować inną odpowiedź?
Ajedi32
1
Niezłe rozwiązanie. Wokół odpowiedzi Domiego umieściłem kilka innych metod, dzięki czemu mogę - uzyskać (potencjalnie) obcięty ciąg z elipsą (...) na końcu, jeśli nie zmieści się on w danym miejscu (tak dużej części łańcucha) jak to będzie możliwe) - Przekaż element JQuery, który ma zawierać (ewentualnie obcięty) ciąg, i określ dynamicznie atrybuty czcionki, aby nie musiały być zakodowane na stałe, umożliwiając zmianę atrybutów czcionki CSS bez zerwania Układ. JSFiddle Tutaj: jsfiddle.net/brebey/1q94gLsu/6/embed
BRebey
2
Dobrze, ponieważ użytkownik tego nie widzi!
clabe45
110

Oto jeden, który wymieszałem bez przykładu. Wygląda na to, że wszyscy jesteśmy na tej samej stronie.

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

Korzystanie z niego jest proste: "a string".width()

** Dodano, white-space: nowrapaby można było obliczyć ciągi o szerokości większej niż szerokość okna.

Bob Monteverde
źródło
2
Dzięki JordanC. Chciałbym dodać, że jeśli często dzwonisz na tej samej stronie, a wydajność jest problemem, możesz zachować DIV, po prostu zmienić zawartość i sprawdzić szerokość. Zrobiłem to w ten sposób, więc gdy wszystko zostanie już powiedziane i zrobione, DOM będzie taki sam, jak na początku
Bob Monteverde
3
Nie dodawałbym tej metody, Stringponieważ zmniejsza to rozdzielenie obaw twojego programu (oddzielny kod podstawowy vs. kod interfejsu użytkownika). Wyobraź sobie, że chcesz przenieść swój kod główny na platformę z zupełnie innym frameworkiem interfejsu użytkownika ...
Domi
23
To zły projekt , który nie tylko łączy twój model z twoim widokiem, ale także łączy go bezpośrednio z jQuery. Ponadto jest to piekło rozpływowe, zdecydowanie nie byłoby dobrze skalowane.
James
1
Jeśli chcesz wartość zmiennoprzecinkowa, możesz użyć o[0].getBoundingClientRect().widthzgodnie z sugestią tutaj: stackoverflow.com/a/16072668/936397
Alexander Olsson
1
@virus dobrze powiedział, że ponad 100 osób prawdopodobnie nie dba o wydajność ... Niemniej nie czyni tego, co powiedziałem, mniej ważnym lub prawdziwym.
James
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);
Deepak Nadar
źródło
26

To działa dla mnie ...

// 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;
}
Pete
źródło
Cześć, twoja odpowiedź jest naprawdę pomocna, jednak użyj .cssText zamiast .style do obsługi IE 8 i niższych ..
Dilip Rajkumar
Ta odpowiedź jest świetna, ale kiedy generuję duży fragment tekstu, staje się on niedokładny o kilka pikseli. Czy to dlatego, że szerokość nie jest liczbą całkowitą?
Bobtroopo
20

Przez biblioteki ExtJS obsługa JavaScript ma wielką klasę o nazwie Ext.util.TextMetrics że „zapewnia precyzyjne pomiary pikseli dla bloków tekstu, dzięki czemu można dokładnie określić, jak wysokie i szerokie, w pikselach, dany blok tekstu będzie”. Możesz użyć go bezpośrednio lub wyświetlić jego kod źródłowy, aby zobaczyć, jak to się robi.

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

wielki lep
źródło
1
ExtJS ma dziwną licencję. Albo płacisz obecnym opiekunom, firmie Sencha, aby z niego korzystali, albo musisz otworzyć cały kod związany z aplikacją. To jest przystanek dla większości firm. Z drugiej strony jQuery korzysta z wysoce liberalnej licencji MIT.
devdanke
1
Czy javascript nie spełnia automatycznie wymagań open source? Podajesz źródło każdemu, kto przegląda stronę.
PatrickO
10
Istnieje różnica między możliwością przeglądania kodu źródłowego a otwartym kodem źródłowym, który jest określony przez licencjonowanie.
Parker Ault,
Dzięki tym z nas, którzy nadal używają ExtJS :-)
Monarch Wadia
1
powinieneś pozwolić ExtJS spoczywać w pokoju
canbax
19

Podoba mi się twój „jedyny pomysł” zrobienia statycznej mapy szerokości postaci! W rzeczywistości działa dobrze dla moich celów. Czasami, ze względu na wydajność lub ponieważ nie masz łatwego dostępu do DOM, możesz po prostu chcieć szybkiego, samodzielnego kalkulatora skalibrowanego do pojedynczej czcionki. Oto jeden skalibrowany do Helvetica; przekazać ciąg i (opcjonalnie) rozmiar czcionki:

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
}

Ta olbrzymia brzydka tablica ma szerokość znaków ASCII indeksowaną kodem znaków. To obsługuje tylko ASCII (w przeciwnym razie zakłada średnią szerokość znaków). Na szczęście szerokość zasadniczo skaluje się liniowo z rozmiarem czcionki, więc działa całkiem dobrze przy każdym rozmiarze czcionki. Zauważalnie brakuje mu świadomości kerningu, ligatur czy czegokolwiek innego.

Aby „skalibrować” po prostu renderowałem każdą postać do charCode 126 (potężna tylda) na pliku svg, dostałem obwiednię i zapisałem ją w tej tablicy; więcej kodu, wyjaśnienia i demo tutaj .

Toph
źródło
1
to sprytne rozwiązanie, fajne :) Zawsze używam tej samej czcionki / rozmiaru, więc mi to odpowiada. Wydajność rozwiązań DOM / Canvas była dla mnie prawdziwym problemem, to jest naprawdę czyste, na zdrowie!
mikeapr4
1
usuwa potrzebę płótna +1
frage
Możesz się ich pozbyć * fontSizei po prostu ich użyć
Matt Fletcher
Cóż za niesamowita odpowiedź!
almosnow
11

Napisałem do tego małe narzędzie. Być może jest to przydatne dla kogoś. Działa bez jQuery .

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

Stosowanie:

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

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

Fiddle: http://jsfiddle.net/PEvL8/

chickling
źródło
7

Możesz użyć płótna, abyś nie musiał tak bardzo zajmować się właściwościami 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;
rysama
źródło
Czy to nie jest o wiele bardziej ciężki (z uzyskaniem kontekstu 2d itp.) Niż tworzenie elementu DOM i określanie dla niego właściwości css?
Pharao2k 18.04.13
1
To czyste podejście, jeśli już do czegoś używasz płótna. Ale bardzo wolno. Samo wywołanie MeasureText zajmuje około 8-10 ms (w przeglądarce Chrome).
Rui Marques
6
<span id="text">Text</span>

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

Powinno to działać tak długo, jak długo znacznik <span> nie ma do niego zastosowania żadne inne style. offsetWidth obejmie szerokość dowolnych granic, dopełnienie w poziomie, szerokość pionowego paska przewijania itp.

Bryan Friedman
źródło
Mniej więcej to czyni górnymi rozwiązaniami, ale ponieważ tekst może być podzielony na kilka linii, dodają do niego style CSS, aby uzyskać rzeczywistą pełną szerokość tekstu.
Adrian Maire
2

Poniższe fragmenty kodu „obliczają” szerokość znacznika span, dodają do niego „...”, jeśli jest za długi i zmniejsza długość tekstu, dopóki nie dopasuje się do elementu nadrzędnego (lub dopóki nie spróbuje więcej niż tysiąc razy)

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 (z 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)
        }
    }
});
Techek
źródło
2
Spróbuj wyszukać binarnie zamiast zapętlać 1 znak na raz: zobacz mój komentarz do odpowiedzi Alexa na stackoverflow.com/questions/536814/…
StanleyH
@StanleyH: Dobry pomysł - jak najszybciej zrealizuję twoją sugestię.
Techek
2

Lepiej jest wykryć, czy tekst będzie pasował tuż przed wyświetleniem elementu. Możesz więc użyć tej funkcji, która nie wymaga wyświetlania elementu na ekranie.

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

Stosowanie:

if ( textWidth("Text", "bold 13px Verdana") > elementWidth) {
    ...
}
artnikpro
źródło
2

Na wypadek, gdyby ktoś tu przybył i szukał zarówno sposobu pomiaru szerokości łańcucha, jak i sposobu określenia, jaki jest największy rozmiar czcionki pasujący do określonej szerokości, oto funkcja oparta na rozwiązaniu @ Domi z wyszukiwaniem binarnym :

/**
 * 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;
        }
    }
}
M. Katz
źródło
Działa to niesamowicie (w połączeniu z kodem z odpowiedzi Domi)
r3wt
1

Wypróbuj ten kod:

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;
}
Jason Bracey
źródło
1

Szerokość i wysokość tekstu można uzyskać za pomocą clientWidthiclientHeight

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

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

upewnij się, że właściwość position stylu jest ustawiona na wartość bezwzględną

element.style.position = "absolute";

nie musi znajdować się w a div, może znajdować się w a plub aspan

Gja
źródło
1

Opierając się na odpowiedzi Deepaka Nadara , zmieniłem parametr funkcji, aby akceptować style tekstu i czcionek. Nie musisz odwoływać się do elementu. Ponadto fontOptionsmają wartości domyślne, więc nie trzeba podawać ich wszystkich.

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

Pan Polywhirl
źródło
0

Wydaje mi się, że jest to podobne do wpisu Depaka, ale oparte jest na pracy Louisa Lazarisa opublikowanej w artykule na imponującej stronie internetowej

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

Zdarzenie dopasowania służy do natychmiastowego wykonania wywołania funkcji po przypisaniu funkcji do sterowania.

np .: $ („input”). autofit (). trigger („fit”);

Mauricio
źródło
0

Bez 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);
v1r00z
źródło
po ustawieniu liczby nie działa, ponieważ nie ma potrzeby wprowadzania spacji, jeśli ją usuniesz, będzie działać dobrze: fontSize + „px arial” -> fontSize + „px arial”, tylko tyle.
Alberto Acuña
0

Skrzypek przykładowego działania: 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>

Kod 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");
Jason Williams
źródło
0

Element.getClientRects()Metoda zwraca kolekcję DOMRectobiektów, które wskazują okalającym prostokątów dla każdego pola granicznego CSS w kliencie. Zwrócona wartość to zbiór DOMRectobiektów, po jednym dla każdego pola obramowania CSS związanego z elementem. Każdy DOMRectobiekt zawiera tylko do odczytu left, top, righti bottomwłaściwości opisujące pole obramowania w pikselach z lewego górnego w stosunku do górnej lewej rzutni.

Element.getClientRects () firmy Mozilla Contributors jest licencjonowany na licencji CC-BY-SA 2.5 .

Zsumowanie wszystkich zwróconych szerokości prostokąta daje całkowitą szerokość tekstu w pikselach.

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>

tranzystor09
źródło
0

Zrobiłem mały moduł ES6 (używa 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();
}

Łatwy w użyciu:

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

Fajna rzecz, którą możesz zauważyć - pozwala uwzględnić wszelkie atrybuty CSS, nawet wypełnienia!

Roman86
źródło
0

Możesz to również zrobić za pomocą createRange, który jest dokładniejszy niż technika klonowania tekstu:

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;
}
Inc33
źródło
-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'));
kavun
źródło