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.

Jacob
quelle
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>

CMPalmer
quelle
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).

Domi
quelle
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.

Bob Monteverde
quelle
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);
Deepak Nadar
quelle
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;
}
Pete
quelle
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

großer lep
quelle
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 .

Toph
quelle
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
11

Ich habe ein kleines Tool dafür geschrieben. Vielleicht ist es für jemanden nützlich. Es funktioniert ohne jQuery .

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

Verwendungszweck:

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

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

Geige: http://jsfiddle.net/PEvL8/

schickling
quelle
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;
Rysama
quelle
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.

Bryan Friedman
quelle
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)
        }
    }
});
Techek
quelle
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) {
    ...
}
artnikpro
quelle
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;
        }
    }
}
M Katz
quelle
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;
}
Jason Bracey
quelle
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

Gjaa
quelle
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>

Mr. Polywhirl
quelle
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");

Mauricio
quelle
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);
v1r00z
quelle
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");
Jason Williams
quelle
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>

Transistor09
quelle
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!

Roman86
quelle
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;
}
Inc33
quelle
-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
quelle