Start · Sprachen · JavaScript · Referenz · TextMetrics

TextMetrics

Schnittstelle

Beschreibt die Abmessungen eines Textstücks im Canvas; Instanzen liefert <code>CanvasRenderingContext2D.measureText()</code>.

seit JavaScript Baseline: alle Browser (width); erweiterte Eigensc Kategorie: webapi

Signatur

interface TextMetrics

Beschreibung

TextMetrics ist ein reines Datenobjekt mit schreibgeschützten Eigenschaften. Es gibt Auskunft darüber, wie viel Platz ein Text mit den aktuellen Einstellungen des Kontexts belegt, also mit font, textAlign, textBaseline, direction und letterSpacing. Einen eigenen Konstruktor gibt es nicht. Eine Instanz bekommen Sie nur über ctx.measureText(text) auf einem CanvasRenderingContext2D oder OffscreenCanvasRenderingContext2D.

Die wichtigsten Eigenschaften (alle in CSS-Pixeln, Typ number):

  • width: Breite des Texts nach dem Vorschub (Advance Width), also der Abstand bis zur Position des nächsten Zeichens.
  • actualBoundingBoxLeft / actualBoundingBoxRight: Abstand vom Ausrichtungspunkt (textAlign) bis zum linken bzw. rechten Rand der tatsächlich gezeichneten Glyphen.
  • actualBoundingBoxAscent / actualBoundingBoxDescent: Abstand von der Grundlinie (textBaseline) bis zur Ober- bzw. Unterkante der tatsächlich gezeichneten Glyphen.
  • fontBoundingBoxAscent / fontBoundingBoxDescent: Ober- bzw. Unterlänge der Schrift selbst, unabhängig vom konkreten Text. Damit erhalten Sie eine gleichbleibende Zeilenhöhe.
  • emHeightAscent / emHeightDescent: Abstand von der Grundlinie bis zur Ober- bzw. Unterkante des Em-Quadrats.
  • hangingBaseline, alphabeticBaseline, ideographicBaseline: Lage der jeweiligen Grundlinie, gemessen von der Grundlinie, die in textBaseline eingestellt ist.

Typische Einsatzfälle: Text zentrieren oder rechtsbündig ausrichten, Text in einer festen Breite umbrechen, Hintergrund-Boxen oder Tooltips passgenau hinter Beschriftungen zeichnen, Diagrammachsen beschriften und Kollisionen zwischen Labels erkennen. Für die sichtbare Höhe eines Texts nehmen Sie actualBoundingBox*. Für eine gleichmäßige Zeilenhöhe über mehrere Zeilen nehmen Sie fontBoundingBox*.

Rückgabewert

Typ
TextMetrics
Beschreibung
Wird von measureText(text) zurückgegeben. Alle Eigenschaften sind schreibgeschützt und vom Typ number (in CSS-Pixeln).

Beispiele

Instanz über measureText() erzeugen und auslesen

const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.font = '24px sans-serif';

const metrics = ctx.measureText('Hallo Welt');
console.log(metrics instanceof TextMetrics);
console.log('Breite:', metrics.width.toFixed(1));
console.log('Sichtbare Höhe:',
  (metrics.actualBoundingBoxAscent + metrics.actualBoundingBoxDescent).toFixed(1));
true Breite: 118.7 Sichtbare Höhe: 23.1 (Die Zahlenwerte hängen von Schrift und Plattform ab.)

Beschriftung mit passgenauer Hintergrund-Box

const ctx = document.querySelector('canvas').getContext('2d');
ctx.font = 'bold 18px system-ui';
ctx.textBaseline = 'alphabetic';

const drawLabel = (text, x, y, padding = 6) => {
  const m = ctx.measureText(text);
  const left = x - m.actualBoundingBoxLeft - padding;
  const top = y - m.fontBoundingBoxAscent - padding;
  const width = m.actualBoundingBoxLeft + m.actualBoundingBoxRight + padding * 2;
  const height = m.fontBoundingBoxAscent + m.fontBoundingBoxDescent + padding * 2;

  ctx.fillStyle = '#1e293b';
  ctx.fillRect(left, top, width, height);
  ctx.fillStyle = '#fff';
  ctx.fillText(text, x, y);
};

drawLabel('Umsatz 2024', 40, 60);

Text auf eine maximale Breite umbrechen

const wrapText = (ctx, text, maxWidth) => {
  const words = text.split(' ');
  const lines = [];
  let line = '';
  for (const word of words) {
    const test = line ? `${line} ${word}` : word;
    if (ctx.measureText(test).width > maxWidth && line) {
      lines.push(line);
      line = word;
    } else {
      line = test;
    }
  }
  if (line) lines.push(line);
  return lines;
};

const ctx = document.querySelector('canvas').getContext('2d');
ctx.font = '16px Georgia';
const m = ctx.measureText('Mg');
const lineHeight = m.fontBoundingBoxAscent + m.fontBoundingBoxDescent;

wrapText(ctx, 'Ein längerer Absatz, der automatisch auf mehrere Zeilen verteilt wird.', 180)
  .forEach((l, i) => ctx.fillText(l, 10, 30 + i * lineHeight));

Text mit OffscreenCanvas im Worker messen

const off = new OffscreenCanvas(1, 1);
const octx = off.getContext('2d');
octx.font = '14px monospace';

const widths = ['a', 'abc', 'abcdef'].map(t => Math.round(octx.measureText(t).width));
console.log(widths);
[8, 25, 50] (ungefähr, je nach Schrift)

// Wichtig · Fallstricke

  • Kein Konstruktor: new TextMetrics() wirft einen TypeError. Instanzen entstehen nur über measureText().
  • Nur eine Momentaufnahme: Das Objekt aktualisiert sich nicht. Wenn Sie font, textAlign oder textBaseline ändern, müssen Sie neu messen.
  • Webfonts: Messen Sie erst, wenn die Schrift geladen ist, zum Beispiel nach await document.fonts.load('16px MeineSchrift'). Sonst beziehen sich die Werte auf die Ersatzschrift.
  • Breite ist nicht gleich sichtbare Ausdehnung: width ist die Vorschubbreite. Kursive oder überhängende Glyphen können darüber hinausragen. Für exakte Ränder nehmen Sie actualBoundingBoxLeft + actualBoundingBoxRight.
  • Vorzeichen: actualBoundingBoxLeft ist positiv, wenn der Text links vom Ausrichtungspunkt beginnt. Je nach textAlign und textBaseline können die Werte auch negativ werden.
  • Kompatibilität: width funktioniert überall. Die actualBoundingBox*-Werte sind in allen modernen Browsern verfügbar. fontBoundingBox* gibt es in Firefox erst ab Version 116. emHeight* und die *Baseline-Eigenschaften sind erst seit etwa 2023 breit verfügbar. Prüfen Sie im Zweifel vorher, ob die Eigenschaft existiert, z. B. mit 'fontBoundingBoxAscent' in metrics.
  • Leistung: Bei vielen Messungen, etwa beim Umbrechen langer Texte, lohnt es sich, Wortbreiten pro Schrift in einer Map zwischenzuspeichern.
  • Datenschutz: Die Messwerte hängen von installierten Schriften und der Plattform ab. Sie werden deshalb für Browser-Fingerprinting genutzt. Manche Browser (z. B. Tor, Brave) verfälschen die Werte darum leicht.