it-swarm-eu.dev

Vypočítejte šířku textu pomocí JavaScriptu

Chci použít JavaScript pro výpočet šířky řetězce. Je to možné, aniž byste museli používat písmo typu monospace?

Pokud to není vestavěné, moje jediná myšlenka je vytvořit tabulku šířek pro každou postavu, ale to je docela nerozumné, zejména s podporou Unicode a různých velikostí typů (a všech prohlížečů na to záleží).

395
Jacob

Vytvořte styl DIV s následujícími styly. Ve vašem JavaScriptu nastavte velikost písma a atributy, které se pokoušíte změřit, vložte řetězec do DIV a přečtěte si aktuální šířku a výšku DIV. To se roztáhne, aby se vešly do obsahu a velikost bude v rámci několika pixelů vykreslené velikosti řetězce.

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>

316
CMPalmer

V aplikaci HTML 5 můžete použít metodu Canvas.measureText (další vysvětlení zde ).

Zkuste toto housle :

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

Toto fiddle porovnává tuto metodu Canvas s variantou metodou DOM/Boba Monteverdeho , takže můžete analyzovat a porovnávat přesnost výsledků.

Tento přístup má několik výhod, včetně:

  • Stručnější a bezpečnější než jiné metody (DOM), protože nemění globální stav, například DOM.
  • Další přizpůsobení je možné úpravou více vlastností plátna , například textAlign a textBaseline.

Poznámka: Pokud přidáte text do DOM, nezapomeňte také vzít v úvahu výplň, okraj a ohraničení .

POZNÁMKA 2: U některých prohlížečů tato metoda poskytuje přesnost sub-pixelů (výsledkem je číslo s plovoucí desetinnou čárkou), u ostatních to není (výsledek je pouze int). Chcete-li se vyvarovat nekonzistencí, můžete spustit výsledek Math.floor (nebo Math.ceil). Protože metoda založená na DOM není nikdy sub-pixelová přesná, má tato metoda ještě vyšší přesnost než ostatní metody zde.

Podle tento jsperf (díky přispěvatelům v komentářích), metoda Canvas a metoda založená na DOM jsou přibližně stejně rychlé, pokud je do mezipaměti přidáno ukládání do mezipaměti.Metoda založená na DOM a nepoužíváte Firefox. Ve Firefoxu je tento Canvas method z nějakého důvodu mnohem rychlejší než DOM-based method (od září 2014).

302
Domi

Tady je jeden, který jsem spolu bez příkladu šlehl. Vypadá to, že jsme všichni na stejné stránce.

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

Použití je jednoduché: "a string".width()

** Přidáno white-space: nowrap, takže lze vypočítat řetězce s šířkou větší, než je šířka okna.

105
Bob Monteverde

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);
31
Deepak Nadar

Toto funguje pro mě ...

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

Knihovna ExtJS javascript má skvělou třídu nazvanou Ext.util.TextMetrics, která "poskytuje přesné měření pixelů pro bloky textu, takže můžete přesně určit, jak vysoký a široký, v pixelech, daný blok textu bude" . Můžete jej použít buď přímo, nebo zobrazit jeho zdrojový kód, abyste zjistili, jak se to dělá.

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

19
big lep

Na to jsem napsal malý nástroj. Možná je to pro někoho užitečné. Funguje bez jQuery.

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

Používání:

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

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

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

10
schickling

Líbí se mi vaše "jediná myšlenka" právě dělat statický charakter šířka mapy! Vlastně to funguje dobře pro mé účely. Někdy, z důvodů výkonu nebo protože nemáte snadný přístup k DOM, můžete chtít jen rychlou hacky samostatnou kalkulačku kalibrovanou na jediné písmo. Tady je jeden kalibrovaný na Helveticu; předat řetězec a (volitelně) velikost písma:

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
}

Toto obří ošklivé pole je šířka znaku ASCII indexovaná znakovým kódem. Takže to jen podporuje ASCII (jinak předpokládá průměrnou šířku znaků). Naštěstí se šířka v podstatě měří lineárně s velikostí písma, takže to funguje docela dobře při jakékoliv velikosti písma. Je to zjevně postrádající jakékoli povědomí o kerningu nebo ligaturách nebo cokoliv jiného.

Chcete-li "kalibrovat" jsem jen vykreslil každý znak až charCode 126 (mocný tilde) na svg a dostal ohraničovací rámeček a uložil jej do tohoto pole; více kódu a vysvětlení a demo zde .

7
Toph

Můžete použít plátno, takže nemusíte řešit tolik vlastností 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;
5
rysama
<span id="text">Text</span>

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

To by mělo fungovat tak dlouho, dokud tag <span> nemá žádné jiné styly. OffsetWidth bude obsahovat šířku všech okrajů, horizontální výplň, vertikální šířku posuvníku atd. 

4
Bryan Friedman

Snipy kódu níže, "vypočítávají" šířku značky, připojí k ní "...", pokud je příliš dlouhý a zmenší délku textu, dokud se vejde do svého rodiče (nebo dokud se nepokusí více než tisíckrát)

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

Vyzkoušejte tento kód:

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
Jason Bracey

Stavba mimo Deepak Nadar odpověď , jsem změnil parametr funkce přijmout text a styly písma. Není nutné odkazovat na prvek. fontOptions mají také výchozí hodnoty, takže nemusíte dodávat všechny.

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

1
Mr. Polywhirl

Lepší je zjistit, zda se text vejde přímo před zobrazením prvku. Můžete tedy použít tuto funkci, která nevyžaduje, aby byl prvek na obrazovce.

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

Používání:

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

Šířku a výšku textu lze získat pomocí clientWidth a clientHeight

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

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

ujistěte se, že vlastnost pozice stylu je nastavena na absolutní

element.style.position = "absolute";

nemusí být uvnitř div, může být uvnitř p nebo span

1
Gjaa

Myslím, že toto je prety podobné vstupu Depak, ale je založeno na díle Louise Lazarise zveřejněného na článku na stránce 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);

Událost fit se používá k provedení volání funkce inmediatly po přiřazení funkce k ovládacímu prvku.

např .: $ ('input'), autofit () trigger ("fit");

0
Mauricio

Fiddle of working example: 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>

Kód JavaScriptu:

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
Jason Williams

V případě, že by se sem přišel podívat někdo jiný, jak měřit šířku řetězce a způsob, jak zjistit, jaká je největší velikost písma, která se vejde do určité šířky, je zde funkce, která staví na řešení @ Domi s binárním vyhledáváním:

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

Metoda Element.getClientRects() vrací soubor DOMRect objektů, které označují ohraničující obdélníky pro každé ohraničovací pole CSS v klientovi. Vrácená hodnota je kolekce objektů DOMRect, jedna pro každé ohraničovací pole CSS přidružené k prvku. Každý objekt DOMRect obsahuje vlastnosti left, top, right a bottom, které jsou určeny pouze pro čtení a které popisují rámeček ohraničení v pixelech s levým horním levým horním okrajem výřezu.

Element.getClientRects () by Mozilla Contributors je licencován pod CC-BY-SA 2.5 .

Součtem všech vrácených šířek obdélníku získáte celkovou šířku textu v pixelech.

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
transistor09

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

Udělal jsem malý modul ES6 (používá 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();
}

Snadné použití:

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

Skvělá věc, kterou si můžete všimnout - umožňuje vzít v úvahu všechny atributy CSS, dokonce i výplně!

0
Roman86