Berechnen Sie die Textbreite mit JavaScript


467

Ich möchte JavaScript verwenden, um die Breite eines Strings zu berechnen. Ist dies möglich, ohne eine Monospace-Schrift verwenden zu müssen?

Wenn es nicht integriert ist, besteht meine einzige Idee darin, für jedes Zeichen eine Tabelle mit Breiten zu erstellen. Dies ist jedoch ziemlich unvernünftig, insbesondere wenn Unicode und verschiedene Schriftgrößen (und alle Browser) unterstützt werden.


10
Beachten Sie, dass Sie bei Verwendung externer Schriftarten nach dem Laden die folgenden Techniken anwenden müssen. Sie können dies nicht erkennen, wenn Sie sie zwischengespeichert haben oder wenn Sie lokale Versionen installiert haben.
Seth W. Klein

Antworten:


355

Erstellen Sie einen DIV mit den folgenden Stilen. Legen Sie in Ihrem JavaScript die Schriftgröße und die Attribute fest, die Sie messen möchten, fügen Sie Ihre Zeichenfolge in den DIV ein und lesen Sie dann die aktuelle Breite und Höhe des DIV. Es wird gedehnt, um dem Inhalt zu entsprechen, und die Größe liegt innerhalb weniger Pixel der gerenderten Zeichenfolge.

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
Das einzige, was ich hinzufügen möchte, ist, dass dies abhängig von den verwendeten Stilen möglicherweise die falschen Abmessungen ergibt. Denken Sie daran, dass Sie möglicherweise Stile wie p {Buchstabenabstand: 0.1em; }, die ein DIV-Element nicht widerspiegeln würde. Sie müssen sicherstellen, dass die vorhandenen Stile für den Verwendungszweck des Textes geeignet sind.
Jim

5
Ditto Jims Kommentar - Überprüfen Sie noch einmal, ob auf den Container, in diesem Fall div, keine anderen Stile über CSS-Auswahlregeln angewendet wurden, die Sie zu diesem Zeitpunkt möglicherweise nicht kennen. Entfernen Sie alle relevanten Stile aus dem Behälter, bevor Sie die gewünschten Stile vor dem Messen anwenden.
Jason Bunting

44
Sie sollten auch Leerzeichen einfügen: nowrap, wenn Sie glauben, dass der Text die Breite des Browsers überschreitet.
Herb Caudill

5
@BBog alles, was herumhackt, ist, warum ich unten einen anderen, weniger hackigen Ansatz vorschlage. Schau es dir hier an .
Domi

11
Nur neugierig, wofür das +1in jeder Dimension ist?
Kip

385

In HTML 5 können Sie einfach die Canvas.measureText-Methode verwenden (weitere Erläuterungen hier ).

Versuchen Sie diese Geige :

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

Diese Geige vergleicht diese Canvas-Methode mit einer Variation der DOM-basierten Methode von Bob Monteverde , sodass Sie die Genauigkeit der Ergebnisse analysieren und vergleichen können.

Dieser Ansatz bietet mehrere Vorteile, darunter:

  • Prägnanter und sicherer als die anderen (DOM-basierten) Methoden, da sie den globalen Status wie Ihr DOM nicht ändern.
  • Weitere Anpassungen sind möglich, indem weitere Canvas-Texteigenschaften wie textAlignund geändert werdentextBaseline .

HINWEIS: Denken Sie beim Hinzufügen des Texts zu Ihrem DOM daran, auch Auffüllung, Rand und Rand zu berücksichtigen .

ANMERKUNG 2: In einigen Browsern liefert diese Methode eine Subpixel-Genauigkeit (Ergebnis ist eine Gleitkommazahl), in anderen nicht (Ergebnis ist nur ein Int). Möglicherweise möchten Sie das Ergebnis ausführen Math.floor(oder Math.ceil), um Inkonsistenzen zu vermeiden. Da die DOM-basierte Methode niemals subpixelgenau ist, hat diese Methode eine noch höhere Genauigkeit als die anderen Methoden hier.

Laut diesem jsperf (dank der Mitwirkenden in den Kommentaren) sind die Canvas-Methode und die DOM-basierte Methode ungefähr gleich schnell, wenn der DOM-basierten Methode Caching hinzugefügt wird und Sie Firefox nicht verwenden. In Firefox ist diese Canvas-Methode aus irgendeinem Grund viel schneller als die DOM-basierte Methode (Stand September 2014).


7
Dies ist eine großartige Option, ich wusste nichts davon. Vergleichen Sie jemals die Leistung mit der Leistung der Messung im DOM?
SimplGy

2
Ich habe das Caching zu diesem jsperf-Benchmark hinzugefügt. Jetzt sind die beiden Methoden ziemlich gleichwertig
Brandon Bloom

1
@ Martin Huh? Was haben "viele HTML-Elemente" hier mit irgendetwas zu tun? Das Canvas-Objekt in diesem Beispiel ist nicht einmal an das DOM angehängt. Abgesehen davon wirkt sich das Ändern der Schriftart in einem Leinwandzeichnungskontext erst dann auf die Leinwand aus, wenn Sie strokeText()oder fillText(). Vielleicht wollten Sie eine andere Antwort kommentieren?
Ajedi32

1
Schöne Lösung. Ich habe ein paar andere Methoden um Domis Antwort gewickelt, damit ich - eine (möglicherweise) abgeschnittene Zeichenfolge mit Auslassungspunkten (...) am Ende erhalten kann, wenn sie nicht in ein bestimmtes Leerzeichen passt (so viel von der Zeichenfolge) wird verwendet) - Übergeben Sie ein JQuery-Element, das die (möglicherweise abgeschnittene) Zeichenfolge enthalten soll, und bestimmen Sie die Schriftattribute dynamisch, damit sie nicht fest codiert werden müssen, sodass sich CSS-Schriftattribute ohne Unterbrechung ändern können das Layout. JSFiddle hier: jsfiddle.net/brebey/1q94gLsu/6/embed
BRebey

2
Gut, weil der Benutzer es nicht sieht!
Clabe45

110

Hier ist eine, die ich ohne Beispiel zusammengeschlagen habe. Es sieht so aus, als wären wir alle auf derselben Seite.

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

Die Verwendung ist einfach: "a string".width()

** Es white-space: nowrapwurden Zeichenfolgen hinzugefügt , deren Breite größer als die Fensterbreite ist.


2
Danke JordanC. Eine Sache, die ich hinzufügen möchte, ist, wenn Sie dies häufig auf derselben Seite aufrufen und die Leistung ein Problem darstellt, können Sie den DIV beibehalten und einfach den Inhalt ändern und die Breite überprüfen. Ich habe es einfach so gemacht, und sobald alles gesagt und getan war, war das DOM das gleiche wie zu Beginn
Bob Monteverde,

3
Ich würde diese Methode nicht hinzufügen, Stringda sie die Trennung der Bedenken Ihres Programms verringert (separater Kerncode vs. UI-Code). Stellen Sie sich vor, Sie möchten Ihren Kerncode auf eine Plattform mit einem ganz anderen UI-Framework portieren ...
Domi

23
Dies ist ein schlechtes Design . Es koppelt nicht nur Ihr Modell mit Ihrer Ansicht, sondern auch direkt mit jQuery. Darüber hinaus ist dies die Reflow-Hölle, dies würde definitiv nicht gut skalieren.
James

1
Wenn Sie den Float-Wert möchten, können Sie ihn o[0].getBoundingClientRect().widthwie hier vorgeschlagen verwenden: stackoverflow.com/a/16072668/936397
Alexander Olsson

1
@virus gut gesagt 100+ Leute interessieren sich wahrscheinlich auch nicht für Leistung ... Trotzdem macht das, was ich gesagt habe, nicht weniger gültig oder wahr.
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);

27

Das funktioniert bei mir ...

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

Hallo, Ihre Antwort ist wirklich hilfreich. Verwenden Sie jedoch .cssText anstelle von .style, um IE 8 und niedriger zu unterstützen.
Dilip Rajkumar

Diese Antwort ist großartig, aber wenn ich ein großes Stück Text generiere, werden einige Pixel ungenau. Liegt es daran, dass die Breite keine ganze Zahl ist?
Bobtroopo

20

Die ExtJS-Javascript-Bibliothek verfügt über eine großartige Klasse namens Ext.util.TextMetrics, die "präzise Pixelmessungen für Textblöcke bereitstellt, damit Sie genau bestimmen können, wie hoch und breit ein bestimmter Textblock in Pixel sein wird". Sie können es entweder direkt verwenden oder seine Quelle als Code anzeigen, um zu sehen, wie dies gemacht wird.

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


1
ExtJS hat eine ungerade Lizenz. Entweder bezahlen Sie die aktuellen Betreuer, die Sencha Company, um sie zu verwenden, oder Sie müssen den gesamten zugehörigen Code in Ihrer Anwendung als Open-Source-Code bereitstellen. Dies ist ein Show Stopper für die meisten Unternehmen. jQuery verwendet dagegen die höchst zulässige MIT-Lizenz.
Devdanke

1
Entspricht Javascript nicht automatisch den Anforderungen von Open Source? Sie stellen die Quelle jedem zur Verfügung, der die Seite anzeigt.
PatrickO

10
Es gibt einen Unterschied zwischen der Anzeige des Quellcodes und Open Source, der durch die Lizenzierung definiert wird.
Parker Ault

Vielen Dank von denen von uns, die ExtJS noch verwenden :-)
Monarch Wadia

1
Sie hätten die ExtJS in Frieden ruhen lassen sollen
canbax

19

Ich mag deine "einzige Idee", nur eine statische Zeichenbreiten-Map zu erstellen! Es funktioniert tatsächlich gut für meine Zwecke. Manchmal möchten Sie aus Leistungsgründen oder weil Sie keinen einfachen Zugriff auf ein DOM haben, nur einen schnellen, eigenständigen Taschenrechner, der auf eine einzelne Schriftart kalibriert ist. Also hier ist eine, die auf Helvetica kalibriert ist; Übergeben Sie eine Zeichenfolge und (optional) eine Schriftgröße:

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
}

Dieses riesige hässliche Array besteht aus ASCII-Zeichenbreiten, die durch Zeichencode indiziert werden. Dies unterstützt also nur ASCII (andernfalls wird eine durchschnittliche Zeichenbreite angenommen). Glücklicherweise skaliert die Breite im Wesentlichen linear mit der Schriftgröße, sodass sie bei jeder Schriftgröße ziemlich gut funktioniert. Es fehlt merklich jegliches Bewusstsein für Kerning oder Ligaturen oder was auch immer.

Um "zu kalibrieren", habe ich einfach jedes Zeichen bis zu charCode 126 (der mächtigen Tilde) auf einem SVG gerendert und den Begrenzungsrahmen erhalten und in diesem Array gespeichert. Mehr Code und Erklärung und Demo hier .


1
Das ist eine clevere Lösung, nette :) Ich verwende immer die gleiche Schriftart / Größe, also passt es mir gut. Ich fand die Leistung der DOM / Canvas-Lösungen ein echtes Problem, das ist wirklich sauber, Prost!
Mikeapr4

1
beseitigt die Notwendigkeit für Leinwand +1
Frage

Sie können das loswerden * fontSizeund einfach 'em' verwenden
Matt Fletcher

Was für eine erstaunliche Antwort!
Almosnow


7

Sie können die Zeichenfläche verwenden, damit Sie sich nicht so sehr mit CSS-Eigenschaften befassen müssen:

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;

Ist das nicht viel schwerer (mit dem Abrufen des 2D-Kontexts usw.) als das Erstellen eines DOM-Elements und das Angeben von CSS-Eigenschaften dafür?
Pharao2k

1
Dies ist ein sauberer Ansatz, wenn Sie bereits Leinwand für etwas verwenden. Aber sehr langsam. Allein der MeasureText-Aufruf dauert ca. 8-10 ms (mit Chrome).
Rui Marques

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

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

Dies sollte funktionieren, solange auf das <span> -Tag keine anderen Stile angewendet werden. offsetWidth umfasst die Breite aller Ränder, die horizontale Auffüllung, die Breite der vertikalen Bildlaufleiste usw.


Das ist mehr oder weniger das, was obere Lösungen ausmacht. Da Ihr Text jedoch in mehrere Zeilen aufgeteilt sein kann, fügen sie dem Text einige CSS-Stile hinzu, um die tatsächliche Volltextbreite zu erhalten.
Adrian Maire

2

Die folgenden Code-Schnipsel "berechnen" die Breite des Span-Tags, fügen "..." hinzu, wenn es zu lang ist, und reduzieren die Textlänge, bis es in das übergeordnete Element passt (oder bis es mehr als versucht hat tausendmal)

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 (mit 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
Versuchen Sie eine binäre Suche, anstatt jeweils 1 Zeichen zu schleifen: Siehe meinen Kommentar zu Alex 'Antwort auf stackoverflow.com/questions/536814/…
StanleyH

@ StanleyH: Gute Idee - ich werde Ihren Vorschlag so schnell wie möglich umsetzen.
Techek

2

Am besten erkennen Sie, ob der Text passt, bevor Sie das Element anzeigen. Sie können also diese Funktion verwenden, bei der das Element nicht auf dem Bildschirm angezeigt werden muss.

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

Verwendungszweck:

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

2

Falls hier jemand nach einer Möglichkeit gesucht hat, die Breite eines Strings zu messen und herauszufinden, welche Schriftgröße am größten in eine bestimmte Breite passt, finden Sie hier eine Funktion, die auf der Lösung von @ Domi mit einer binären Suche aufbaut ::

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

Dies funktioniert erstaunlich (zusammen mit dem Code aus
Domis

1

Versuchen Sie diesen Code:

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

Die Breite und Höhe eines Textes kann mit clientWidthund ermittelt werdenclientHeight

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

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

Stellen Sie sicher, dass die Eigenschaft style position auf absolut gesetzt ist

element.style.position = "absolute";

muss nicht in a sein div, kann in a poder a seinspan


1

Aufbauend auf Deepak Nadars Antwort ich die Funktionsparameter geändert, um Text- und Schriftstile zu akzeptieren. Sie müssen kein Element referenzieren. Außerdem fontOptionshaben die Standardeinstellungen, sodass Sie nicht alle angeben müssen.

(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

Ich denke, dies ist dem Eintrag von Depak ziemlich ähnlich, basiert jedoch auf der Arbeit von Louis Lazaris, die in einem Artikel auf der beeindruckenden Seite veröffentlicht wurde

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

Das Fit-Ereignis wird verwendet, um den Funktionsaufruf sofort auszuführen, nachdem die Funktion dem Steuerelement zugeordnet wurde.

zB: $ ('input'). autofit (). trigger ("fit");


0

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

Wenn Sie eine Zahl festlegen, funktioniert dies nicht, da ein Leerzeichen nicht erforderlich ist. Wenn Sie es entfernen, funktioniert es einwandfrei: fontSize + "px arial" -> fontSize + "px arial", genau das.
Alberto Acuña

0

Geige des Arbeitsbeispiels: 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-Code:

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

Die Element.getClientRects()Methode gibt eine Sammlung von DOMRectObjekten zurück, die die Begrenzungsrechtecke für jedes CSS-Rahmenfeld in einem Client angeben. Der zurückgegebene Wert ist eine Sammlung von DOMRectObjekten, eines für jedes dem Element zugeordnete CSS-Rahmenfeld. Jedes DOMRectObjekt enthält schreibgeschützt left, top, rightund bottomEigenschaften der Beschreibung der Grenzkasten in Pixeln mit der oberen linken relativ zur oberen linken Ecke des Ansichtsfensters.

Element.getClientRects () von Mozilla Contributors ist unter CC-BY-SA 2.5 lizenziert .

Das Summieren aller zurückgegebenen Rechteckbreiten ergibt die gesamte Textbreite in Pixel.

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

Ich habe ein winziges ES6-Modul erstellt (verwendet 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();
}

Einfach zu verwenden:

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

Coole Sache, die Sie vielleicht bemerken - es ermöglicht die Berücksichtigung aller CSS-Attribute, sogar von Auffüllungen!


0

Sie können dies auch mit createRange tun, das genauer ist als die Textklontechnik:

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'));
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.