Signatur
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 intextBaselineeingestellt 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
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));
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);
// Wichtig · Fallstricke
- Kein Konstruktor:
new TextMetrics()wirft einenTypeError. Instanzen entstehen nur übermeasureText(). - Nur eine Momentaufnahme: Das Objekt aktualisiert sich nicht. Wenn Sie
font,textAlignodertextBaselineä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:
widthist die Vorschubbreite. Kursive oder überhängende Glyphen können darüber hinausragen. Für exakte Ränder nehmen SieactualBoundingBoxLeft + actualBoundingBoxRight. - Vorzeichen:
actualBoundingBoxLeftist positiv, wenn der Text links vom Ausrichtungspunkt beginnt. Je nachtextAlignundtextBaselinekönnen die Werte auch negativ werden. - Kompatibilität:
widthfunktioniert überall. DieactualBoundingBox*-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
Mapzwischenzuspeichern. - 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.