Calculer la largeur du texte avec JavaScript

467

Je voudrais utiliser JavaScript pour calculer la largeur d'une chaîne. Est-ce possible sans avoir à utiliser une police monospace?

Si ce n'est pas intégré, ma seule idée est de créer un tableau des largeurs pour chaque caractère, mais cela est assez déraisonnable, en particulier en prenant en charge Unicode et différentes tailles de type (et tous les navigateurs d'ailleurs).

Jacob
la source
10
Attention, si vous utilisez des polices externes, vous devrez utiliser les techniques ci-dessous après leur chargement. Vous ne pouvez pas réaliser cela si vous les avez mis en cache ou si vous avez installé des versions locales.
Seth W. Klein

Réponses:

355

Créez un DIV stylisé avec les styles suivants. Dans votre JavaScript, définissez la taille de la police et les attributs que vous essayez de mesurer, placez votre chaîne dans le DIV, puis lisez la largeur et la hauteur actuelles du DIV. Il s'étirera pour s'adapter au contenu et la taille sera à quelques pixels de la taille de la chaîne rendue.

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
la source
8
La seule chose que j'ajouterais, c'est que cela peut donner les mauvaises dimensions selon les styles utilisés. N'oubliez pas que vous pouvez avoir des styles comme p {letter-spacing: 0.1em; } qu'un élément DIV ne refléterait pas. Vous devez vous assurer que les styles en place sont appropriés pour l'endroit où vous allez utiliser le texte.
Jim
5
Commentaire de Ditto Jim - revérifiez pour vous assurer que le conteneur, div dans ce cas, n'a pas d'autres styles qui lui sont appliqués via les règles de sélection css que vous ne connaissez peut-être pas à l'époque. Retirez tous les styles pertinents du récipient avant d'appliquer ceux qui vous intéressent avant de mesurer.
Jason Bunting
44
Vous devez également mettre en blanc: nowrap si vous pensez que le texte dépassera la largeur du navigateur.
Herb Caudill
5
@BBog tout ce piratage est la raison pour laquelle je suggère une approche différente, moins hacky, en bas. Jetez-y un œil ici .
Domi
11
Vous êtes curieux de savoir à quoi +1sert chaque dimension?
Kip
385

En HTML 5 , vous pouvez simplement utiliser la méthode Canvas.measureText (plus d'explications ici ).

Essayez ce violon :

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

Ce violon compare cette méthode Canvas à une variante de la méthode basée sur DOM de Bob Monteverde , afin que vous puissiez analyser et comparer la précision des résultats.

Cette approche présente plusieurs avantages, notamment:

REMARQUE: lorsque vous ajoutez le texte à votre DOM, n'oubliez pas de prendre également en compte le remplissage, la marge et la bordure .

REMARQUE 2: Sur certains navigateurs, cette méthode donne une précision sous-pixel (le résultat est un nombre à virgule flottante), sur d'autres non (le résultat n'est qu'un entier). Vous voudrez peut-être exécuter Math.floor(ou Math.ceil) sur le résultat, pour éviter les incohérences. Étant donné que la méthode basée sur DOM n'est jamais précise en sous-pixels, cette méthode a une précision encore plus élevée que les autres méthodes ici.

Selon ce jsperf (merci aux contributeurs dans les commentaires), la méthode Canvas et la méthode basée sur DOM sont à peu près aussi rapides, si la mise en cache est ajoutée à la méthode basée sur DOM et que vous n'utilisez pas Firefox. Dans Firefox, pour une raison quelconque, cette méthode Canvas est beaucoup plus rapide que la méthode basée sur DOM (en septembre 2014).

Domi
la source
7
C'est une option géniale, je n'en savais rien. Avez-vous déjà comparé les performances de ceci aux performances de mesure dans le DOM?
SimplGy
2
J'ai ajouté la mise en cache à cette référence jsperf. Maintenant, les deux méthodes sont à peu près au pair: jsperf.com/measure-text-width/4
Brandon Bloom
1
@Martin Huh? Qu'est-ce que "de nombreux éléments HTML" ont à voir avec quoi que ce soit ici? L'objet canvas dans cet exemple n'est même pas attaché au DOM. Et même en dehors de cela, la modification de la police dans un contexte de dessin de canevas n'affecte même pas le canevas jusqu'à ce que vous strokeText()ou fillText(). Peut-être vouliez-vous commenter une réponse différente?
Ajedi32
1
Belle solution. J'ai encapsulé quelques autres méthodes autour de la réponse de Domi afin que je puisse - Obtenir une chaîne (potentiellement) tronquée avec des points de suspension (...) à la fin si elle ne tient pas dans un espace donné (autant de la chaîne que possible sera utilisé) - Passez un élément JQuery qui doit contenir la chaîne (éventuellement tronquée) et déterminez les attributs de police dynamiquement afin qu'ils n'aient pas à être codés en dur, permettant aux attributs de police CSS de changer sans se casser la disposition. JSFiddle Ici: jsfiddle.net/brebey/1q94gLsu/6/embed
BRebey
2
Bien parce que l'utilisateur ne le voit pas!
clabe45
110

En voici un que j'ai fouetté sans exemple. Il semble que nous soyons tous sur la même longueur d'onde.

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

Son utilisation est simple: "a string".width()

** Ajouté white-space: nowrapafin que les chaînes avec une largeur supérieure à la largeur de la fenêtre puissent être calculées.

Bob Monteverde
la source
2
Merci JordanC. Une chose que j'ajouterais est que si vous appelez cela plusieurs fois sur la même page et que les performances sont un problème, vous pouvez persister le DIV et simplement changer le contenu et vérifier la largeur. Je viens de le faire de cette façon, donc une fois que tout a été dit et fait, le DOM sera le même que lorsque vous avez commencé
Bob Monteverde
3
Je n'ajouterais pas cette méthode Stringcar elle diminue la séparation des préoccupations de votre programme (code de base séparé vs code d'interface utilisateur). Imaginez que vous souhaitiez porter votre code principal sur une plate-forme avec un cadre d'interface utilisateur très différent ...
Domi
23
C'est un mauvais design , non seulement il couple votre modèle avec votre vue, mais il le couple également directement avec jQuery. En plus de cela, c'est l'enfer de refusion, ce ne serait certainement pas bien évoluer.
James
1
Si vous voulez la valeur flottante, vous pouvez utiliser o[0].getBoundingClientRect().widthcomme suggéré ici: stackoverflow.com/a/16072668/936397
Alexander Olsson
1
@virus a bien dit que plus de 100 personnes ne se soucient probablement pas non plus des performances ... Néanmoins, cela ne rend pas ce que j'ai dit moins valide ou vrai.
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
la source
27

Cela fonctionne pour moi ...

// 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
la source
Salut, votre réponse est vraiment utile, mais utilisez .cssText au lieu de .style pour prendre en charge IE 8 et inférieur ..
Dilip Rajkumar
Cette réponse est excellente, mais lorsque je génère un gros morceau de texte, il devient inexact de quelques pixels. Est-ce parce que la largeur n'est pas un entier?
Bobtroopo
20

La bibliothèque javascript ExtJS possède une grande classe appelée Ext.util.TextMetrics qui "fournit des mesures précises en pixels pour les blocs de texte afin que vous puissiez déterminer exactement quelle hauteur et quelle largeur, en pixels, un bloc de texte donné sera". Vous pouvez l'utiliser directement ou afficher sa source pour coder pour voir comment cela se fait.

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

gros lep
la source
1
ExtJS a une licence étrange. Soit vous payez les mainteneurs actuels, la société Sencha pour l'utiliser, soit vous devez open-source tout le code associé dans votre application. C'est un bouchon d'exposition pour la plupart des entreprises. jQuery, d'autre part, utilise la licence MIT très permissive.
devdanke
1
Le javascript ne répond-il pas automatiquement aux exigences de l'open source? Vous diffusez la source à quiconque consulte la page.
PatrickO
10
Il y a une différence entre pouvoir visualiser le code source et l'open source, qui est défini par la licence.
Parker Ault
Merci de ceux d'entre nous qui utilisent encore ExtJS :-)
Monarch Wadia
1
vous auriez dû laisser l'ExtJS reposer en paix
canbax
19

J'aime votre "seule idée" de faire juste une carte de largeur de caractère statique! Cela fonctionne bien pour mes besoins. Parfois, pour des raisons de performances ou parce que vous n'avez pas facilement accès à un DOM, vous pouvez simplement souhaiter une calculatrice autonome rapide et hacky calibrée à une seule police. Voici donc un calibré pour Helvetica; passez une chaîne et (éventuellement) une taille de police:

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
}

Ce tableau laid géant est des largeurs de caractères ASCII indexées par code de caractère. Donc, cela prend juste en charge ASCII (sinon cela suppose une largeur de caractère moyenne). Heureusement, la largeur évolue essentiellement de façon linéaire avec la taille de la police, donc cela fonctionne assez bien avec n'importe quelle taille de police. Il manque visiblement de conscience du crénage, des ligatures ou autre.

Pour "calibrer" je viens de rendre chaque caractère jusqu'au charCode 126 (le puissant tilde) sur un svg et j'ai obtenu le cadre de délimitation et l'ai enregistré dans ce tableau; plus de code et d'explication et de démonstration ici .

Toph
la source
1
c'est une solution intelligente, sympa :) J'utilise toujours la même police / taille, donc ça me convient bien. J'ai trouvé les performances des solutions DOM / Canvas un vrai problème, c'est vraiment propre, bravo!
mikeapr4
1
supprime le besoin de canvas +1
frage
Vous pouvez vous en débarrasser * fontSizeet les utiliser
Matt Fletcher
Quelle réponse incroyable!
almosnow
11

J'ai écrit un petit outil pour ça. C'est peut-être utile à quelqu'un. Cela fonctionne sans jQuery .

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

Usage:

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

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

Violon: http://jsfiddle.net/PEvL8/

chatouillement
la source
7

Vous pouvez utiliser le canevas pour ne pas avoir à vous soucier autant des propriétés 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
la source
N'est-ce pas beaucoup plus lourd (avec l'obtention du contexte 2D, etc.) que la création d'un élément DOM et la spécification des propriétés CSS pour lui?
Pharao2k
1
Il s'agit d'une approche propre si vous utilisez déjà le canevas pour quelque chose. Mais TRÈS LENT. L'appel de mesureTexte à lui seul prend environ 8 à 10 ms (en utilisant Chrome).
Rui Marques
6
<span id="text">Text</span>

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

Cela devrait fonctionner tant que la balise <span> n'a aucun autre style appliqué. offsetWidth inclura la largeur des bordures, le remplissage horizontal, la largeur de la barre de défilement verticale, etc.

Bryan Friedman
la source
C'est plus ou moins ce qui fait des solutions supérieures, mais comme votre texte peut être divisé en plusieurs lignes, ils ajoutent quelques styles CSS au texte pour obtenir la vraie largeur du texte complet.
Adrian Maire
2

Le code-snips ci-dessous, "calcule" la largeur de la balise span, lui ajoute "..." s'il est trop long et réduit la longueur du texte, jusqu'à ce qu'il rentre dans son parent (ou jusqu'à ce qu'il ait essayé plus de un millier de fois)

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 (avec 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
la source
2
Essayez une recherche binaire au lieu de boucler 1 caractère à la fois: voir mon commentaire sur la réponse d'Alex à stackoverflow.com/questions/536814/…
StanleyH
@StanleyH: Bonne idée - je mettrai en œuvre votre suggestion dès que possible.
Techek
2

Le mieux est de détecter si le texte s’adapte juste avant d’afficher l’élément. Vous pouvez donc utiliser cette fonction qui ne nécessite pas que l'élément soit à l'écran.

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

Usage:

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

Dans le cas où quelqu'un d'autre est venu ici à la fois pour trouver un moyen de mesurer la largeur d'une chaîne et un moyen de savoir quelle est la plus grande taille de police qui conviendra à une largeur particulière, voici une fonction qui s'appuie sur la solution de @ Domi avec une recherche binaire :

/**
 * 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
la source
Cela fonctionne étonnamment (couplé avec le code de la réponse de Domi)
r3wt
1

Essayez ce 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
la source
1

La largeur et la hauteur d'un texte peuvent être obtenues avec clientWidthetclientHeight

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

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

assurez-vous que la propriété de position de style est définie sur absolue

element.style.position = "absolute";

pas obligé d'être à l'intérieur d'un div, peut être à l'intérieur d'un pou d'unspan

Gjaa
la source
1

À partir de la réponse de Deepak Nadar , j'ai changé les paramètres des fonctions pour accepter les styles de texte et de police. Vous n'avez pas besoin de référencer un élément. De plus, ils fontOptionsont des valeurs par défaut, vous n'avez donc pas besoin de tous les fournir.

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

M. Polywhirl
la source
0

Je suppose que cela ressemble à l'entrée de Depak, mais est basé sur le travail de Louis Lazaris publié dans un article sur une page Web impressionnante

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

L'événement fit est utilisé pour exécuter l'appel de fonction immédiatement après que la fonction est associée au contrôle.

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

Mauricio
la source
0

Sans 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
la source
lorsque vous définissez un nombre ne fonctionne pas, car il n'y a pas d'espace nécessaire, si vous le supprimez, cela fonctionnera bien: fontSize + "px arial" -> fontSize + "px arial", juste cela.
Alberto Acuña
0

Violon de l'exemple de travail: 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>

Code 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
la source
0

La Element.getClientRects()méthode renvoie une collection d' DOMRectobjets qui indiquent les rectangles de délimitation pour chaque zone de bordure CSS dans un client. La valeur renvoyée est une collection d' DOMRectobjets, un pour chaque zone de bordure CSS associée à l'élément. Chaque DOMRectobjet contient en lecture seule left, top, rightet bottompropriétés décrivant la zone frontalière, en pixels, avec le parent supérieur gauche au coin supérieur gauche de la fenêtre.

Element.getClientRects () par Mozilla Contributors est sous licence CC-BY-SA 2.5 .

La somme de toutes les largeurs de rectangle renvoyées donne la largeur totale du texte en pixels.

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
la source
0

J'ai fait un petit module ES6 (utilise 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();
}

Facile à utiliser:

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

Chose cool que vous pourriez remarquer - cela permet de prendre en compte tous les attributs CSS, même les rembourrages!

Roman86
la source
0

Vous pouvez également le faire avec createRange, qui est plus précis, qu'avec la technique de clonage de texte:

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
la source
-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
la source