Frage

Ich möchte JavaScript verwenden, um die Breite einer Zeichenfolge zu berechnen. Ist dies möglich, ohne dass eine Breitenschrift benutzen?

Wenn es nicht eingebaut in ist, meine einzige Idee ist, eine Tabelle der Breiten für jedes Zeichen zu schaffen, aber das ist ziemlich unvernünftig besonders unterstützt Unicode und unterschiedliche Schriftgrößen (und alle Browser für diese Angelegenheit).

War es hilfreich?

Lösung

Erstellen Sie ein DIV mit den folgenden Stile gestylt. In Ihrem JavaScript, stellen Sie die Schriftgröße und die Attribute, die Sie in der DIV zu messen, setzen Sie Ihre Zeichenfolge versuchen, dann die aktuelle Breite und Höhe des DIV lesen. Es wird den Inhalt passen strecken und die Größe innerhalb von wenigen Pixeln der Zeichenfolge gemacht Größe sein wird.

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>

Andere Tipps

HTML 5 , können Sie einfach die Canvas.measureText Methode (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 https://stackoverflow.com/questions/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 Leinwand-Methode zu einer Variation von Bob Monte DOM-basierte Methode , so können Sie analysieren, und die Genauigkeit der Ergebnisse vergleichen.

Es gibt mehrere Vorteile dieses Ansatzes, einschließlich:

  • prägnante und sicherer als die anderen (DOM-basierte) Methoden, weil es nicht globalen Zustand, wie Ihr DOM nicht ändert.
  • Eine weitere Anpassung ist möglich, von mehr Leinwand Texteigenschaften zu modifizieren , wie textAlign und textBaseline.

Hinweis: Wenn Sie den Text zu Ihrem DOM hinzufügen möchten, denken Sie daran, auch wegen padding, margin und Grenze nehmen .

Hinweis 2: Bei einigen Browsern, diese Methode liefert Subpixel-Genauigkeit (Ergebnis ist eine Fließkommazahl), auf andere dies nicht der Fall (Ergebnis ist nur ein int). Vielleicht möchten Sie Math.floor (oder Math.ceil) auf das Ergebnis laufen, um Inkonsistenzen zu vermeiden. Da die DOM-basierte Methode nie Subpixel-genau ist, hat diese Methode noch höhere Präzision als die anderen Methoden hier.

Nach dieser jsperf (dank der Mitwirkenden in den Kommentaren), die Leinwand-Methode und DOM-basierte Methode ist etwa gleich schnell, wenn das Caching auf die hinzugefügt wird DOM-basierte Methode und Sie verwenden Firefox nicht. In Firefox, aus irgendeinem Grunde, diese Canvas Methode ist viel viel schneller als die DOM-basierte Methode (Stand September 2014).

Hier ist ein ich zusammen ohne Beispiel gepeitscht. Es sieht aus wie wir alle auf der gleichen Seite sind.

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

es zu verwenden ist einfach: "a string".width()

** hinzugefügt white-space: nowrap so Strings mit einer Breite größer als die Fensterbreite berechnet werden kann.

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

Dies funktioniert für mich ...

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

Die ExtJS Javascript-Bibliothek eine große Klasse hat Ext.util.TextMetrics genannt, dass " liefert präzise Pixelmessungen für Textblocks, so dass sie genau, wie hoch und breit in Pixeln ein gegebener Textblock wird bestimmen könnt, sein“. Sie können entweder direkt verwenden oder seine Quelle sehen Code zu sehen, wie das gemacht wird.

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

Ich schrieb ein kleines Tool dafür. Vielleicht ist es sinnvoll, jemanden. Es funktioniert ohne jQuery .

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

Verbrauch:

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

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

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

Ich mag deine „nur Idee“ nur eine statische Zeichenbreite Karte zu tun! Es funktioniert tatsächlich gut für meine Zwecke. Manchmal aus Performance-Gründen oder weil Sie nicht einfachen Zugang zu einem DOM haben, können Sie nur wollen einen schnellen Hacky Standalone-Rechner zu einer einzigen Schriftart kalibriert. Also hier ist eine zu Helvetica kalibriert; übergeben Sie einen String 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
}

Das Riesen hässliche Array ist ASCII-Zeichenbreiten von Zeichencode indiziert. Also das ASCII nur unterstützt (sonst nimmt sie eine durchschnittliche Zeichenbreite). Zum Glück, Breite grundsätzlich skaliert linear mit Schriftgröße, so dass es funktioniert ziemlich gut zu jeder Schriftgröße. Es ist deutlich jedes Bewusstsein für Kerning oder Ligaturen fehlt oder was auch immer.

Um „zu kalibrieren“ Ich gerendert nur jedes Zeichen bis zu charCode 126 (die mächtigen Tilde) auf einem svg und bekam den Begrenzungsrahmen und speicherte es auf dieses Array; mehr Code und Erklärung und Demo hier .

Sie können die Leinwand verwenden, so dass Sie so viel Sie nicht mit CSS-Eigenschaften zu tun haben:

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;
<span id="text">Text</span>

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

Dies sollte funktionieren, solange der Tag keine anderen Stile angewandt wird. offset die Breite irgend Grenzen, horizontal padding, vertikal scrollbar Breite umfasst usw.

Die Code-snips unten, „berechnen“ die Breite der Spanne-tag, anhängt „...“, um es, wenn es zu lange und reduziert die Text-Länge, bis er in seiner Mutter passt (oder bis es hat haben versucht, mehr als tausend mal)

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

Versuchen Sie diesen Code ein:

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

Die Breite und die Höhe eines Textes kann mit clientWidth und clientHeight erhalten werden

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

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

stellen Sie sicher, dass Artposition Eigenschaft auf absolute gesetzt

element.style.position = "absolute";

nicht erforderlich innerhalb eines div zu sein, kann innerhalb eines p oder ein span

sein

Je besser der ist zu erkennen, ob der Text paßt genau, bevor Sie das Element angezeigt werden soll. So können Sie diese Funktion benutzen, die nicht das Element nicht benötigt auf dem Bildschirm zu sein.

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

Verbrauch:

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

Gebäude weg von Deepak Nadars Antwort , änderte ich den Text und Schriftstile Funktionen Parameter zu akzeptieren. Sie brauchen nicht ein Element zu verweisen. Auch die fontOptions Standardwerte haben, so dass Sie nicht brauchen, um sie alle zu versorgen.

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

Falls jemand andere hier bekam beide auf der Suche nach einer Möglichkeit, die Breite einer Zeichenfolge zu messen und eine Möglichkeit zu wissen, was ist die größte Schriftgröße, die in einer bestimmten Breite paßt, ist hier eine Funktion dass baut auf @ Domi-Lösung mit einer binären Suche:

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

Ich denke, das prety ähnlich Eintritt in Depak, sondern basiert auf der Arbeit von Louis Lazaris in einem Artikel in impressivewebs

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

Die Passform Ereignis verwendet wird, um den Funktionsaufruf auszuführen inmediatly nach der Funktion der Steuer asociated wird.

z.B .: $ ( 'input') autofit () Trigger ( "fit");..

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

Fiddle von Arbeitsbeispiel: 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");
  

Die Element.getClientRects() Methode gibt eine Sammlung von Objekten, die die DOMRect Hüllrechtecke für jede CSS border-Box in einem Client anzuzeigen. Der zurückgegebene Wert ist eine Sammlung von Objekten DOMRect, einem für jeden CSS Grenzkasten mit dem Elemente verbunden ist. Jedes Objekt enthält DOMRect schreibgeschützt left, top, right und bottom Eigenschaften der Beschreibung der Grenzkasten in Pixeln mit der oberen linken relativ zur oberen linken Ecke des Ansichtsfensters.

Element.getClientRects () von < a href = "https://developer.mozilla.org/en-US/docs/Web/API/Element/getClientRects$history" rel = "nofollow noreferrer"> Mozilla Mitwirkende unter CC-BY-SA 2.5 .

alle zurück Rechteck Breiten zusammenfassend ergibt die Gesamttextbreite 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>

Ich habe ein kleines ES6 Modul gemacht (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 bedienen:

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

Cool, was Sie vielleicht bemerkt - es zu berücksichtigen, erlaubt keine CSS-Attribute, auch Polsterungen

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'));
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top