605 Stimmen

Berechnen der Textbreite mit JavaScript

Ich möchte JavaScript verwenden, um die Breite einer Zeichenkette zu berechnen. Ist dies möglich, ohne eine Monospace-Schriftart verwenden zu müssen?

Wenn es nicht eingebaut ist, ist meine einzige Idee, eine Tabelle der Breiten für jedes Zeichen zu erstellen, aber das ist ziemlich unvernünftig vor allem Unterstützung Unicode und verschiedenen Schriftgrößen (und allen Browsern, was das betrifft).

595voto

Domi Punkte 18235

En HTML 5 können Sie einfach die Canvas.measureText-Methode (weitere Erklärung aquí ).

Versuchen Sie diese Fiedel :

/**
  * 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
  const canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas"));
  const context = canvas.getContext("2d");
  context.font = font;
  const metrics = context.measureText(text);
  return metrics.width;
}

function getCssStyle(element, prop) {
    return window.getComputedStyle(element, null).getPropertyValue(prop);
}

function getCanvasFontSize(el = document.body) {
  const fontWeight = getCssStyle(el, 'font-weight') || 'normal';
  const fontSize = getCssStyle(el, 'font-size') || '16px';
  const fontFamily = getCssStyle(el, 'font-family') || 'Times New Roman';

  return `${fontWeight} ${fontSize} ${fontFamily}`;
}

console.log(getTextWidth("hello there!", "bold 12pt arial"));  // close to 86

Wenn Sie die Schriftgröße eines bestimmten Elements verwenden möchten myEl können Sie die Funktion getCanvasFontSize Nutzenfunktion:

const fontSize = getTextWidth(text, getCanvasFontSize(myEl));
// do something with fontSize here...

Erläuterung: Die getCanvasFontSize Funktion nimmt einige Elemente (standardmäßig: die body Schriftart und wandelt sie in ein Format um, das mit dem Eigenschaft Context.font . Natürlich muss jedes Element vor der Verwendung zunächst dem DOM hinzugefügt werden, da es sonst falsche Werte liefert.

el.remove()); // hackfix: Tu das nicht! return el; } console.log(getTextWidth( "hallo!", getCanvasFontSize(createEl('span'))) )); console.log(getTextWidth( "hallo!", getCanvasFontSize(createEl('h1')) )); ``` -->

Weitere Anmerkungen

Dieser Ansatz hat mehrere Vorteile, unter anderem:

  • Prägnanter und sicherer als die anderen (DOM-basierten) Methoden, da sie den globalen Zustand, wie z. B. Ihr DOM, nicht verändern.
  • Weitere Anpassungen sind möglich durch Ändern weiterer Eigenschaften von Leinwandtext , wie zum Beispiel textAlign y textBaseline .

HINWEIS: Wenn Sie den Text zu Ihrem DOM hinzufügen, denken Sie daran, auch folgende Punkte zu berücksichtigen Polsterung, Rand und Umrandung .

HINWEIS 2: Bei einigen Browsern liefert diese Methode eine Sub-Pixel-Genauigkeit (das Ergebnis ist eine Fließkommazahl), bei anderen nicht (das Ergebnis ist nur ein int). Sie sollten daher die Methode Math.floor (oder Math.ceil ) auf das Ergebnis, um Inkonsistenzen zu vermeiden. Da die DOM-basierte Methode nie subpixelgenau ist, hat diese Methode eine noch höhere Präzision als die anderen Methoden hier.

Nach Angaben von dieser jsperf (Dank an die Kommentatoren), die Canvas-Methode und die DOM-basierte Methode sind in etwa gleich schnell, wenn das Caching der DOM-basierte Methode und Sie verwenden nicht Firefox. In Firefox, aus irgendeinem Grund, diese Canvas-Methode ist viel, viel schneller als die DOM-basierte Methode (Stand: September 2014).

Leistung

Diese Fiedel vergleicht diese Canvas-Methode mit einer Variante von Die DOM-basierte Methode von Bob Monteverde so dass Sie die Genauigkeit der Ergebnisse analysieren und vergleichen können.

413voto

CMPalmer Punkte 8409

Erstellen Sie ein DIV, das mit den folgenden Stilen gestaltet ist. Legen Sie in Ihrem JavaScript die Schriftgröße und die Attribute fest, die Sie zu messen versuchen, fügen Sie Ihre Zeichenfolge in das DIV ein, und lesen Sie dann die aktuelle Breite und Höhe des DIV aus. Das DIV wird so gestreckt, dass es sich dem Inhalt anpasst und die Größe nur wenige Pixel von der gerenderten Größe der Zeichenfolge entfernt ist.

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>

117voto

Bob Monteverde Punkte 1710

Hier ist eine, die ich ohne Beispiel zusammengeschustert habe. Es sieht so aus, als wären wir alle auf der gleichen 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()

**Zusatz white-space: nowrap so dass Zeichenketten mit einer Breite, die größer als die Fensterbreite ist, berechnet werden können.

37voto

Toph Punkte 2241

Ich mag deine "einzige Idee", einfach eine statische Zeichenkarte zu erstellen! Es funktioniert tatsächlich gut für meine Zwecke. Manchmal, aus Gründen der Leistung oder weil Sie keinen einfachen Zugang zu einem DOM haben, können Sie nur eine schnelle hacky Standalone-Rechner kalibriert, um eine einzelne Schriftart wollen. Hier ist also einer, der auf Helvetica kalibriert ist; übergeben Sie eine Zeichenkette und eine Schriftgröße:

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

function measureText(str, fontSize) {
  return Array.from(str).reduce(
    (acc, cur) => acc + (widths[cur.charCodeAt(0)] ?? avg), 0
  ) * fontSize
}

Dieses riesige hässliche Array besteht aus ASCII-Zeichenbreiten, die nach Zeichencode indiziert sind. Dies unterstützt also nur ASCII (ansonsten wird eine durchschnittliche Zeichenbreite angenommen). Glücklicherweise skaliert die Breite grundsätzlich linear mit der Schriftgröße, so dass es bei jeder Schriftgröße ziemlich gut funktioniert. Es ist merklich fehlt jedes Bewusstsein für Kerning oder Ligaturen oder was auch immer.

Um zu "kalibrieren", habe ich einfach jedes Zeichen bis charCode 126 (die mächtige Tilde) auf ein svg gerendert und die Bounding Box erhalten und in diesem Array gespeichert; mehr Code und Erklärung und Demo hier .

35voto

Pete Punkte 754

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.textContent = pText;

    var lResult = {
        width: lDiv.clientWidth,
        height: lDiv.clientHeight
    };

    document.body.removeChild(lDiv);
    lDiv = null;

    return lResult;
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X