Signatur
Beschreibung
Die Eigenschaft width eines TextMetrics-Objekts gibt an, wie weit der Text den Zeichenstift horizontal vorschiebt – also die Vorschubbreite des Inline-Blocks in CSS-Pixeln. Man erhält ein TextMetrics-Objekt über CanvasRenderingContext2D.measureText() oder OffscreenCanvasRenderingContext2D.measureText().
Typische Einsatzfälle sind das manuelle Zentrieren oder Ausrichten von Text, automatische Zeilenumbrüche im Canvas, das Kürzen von Beschriftungen mit Auslassungspunkten, das Dimensionieren von Hintergrund-Boxen hinter Labels sowie die Berechnung von Achsenbeschriftungen in Diagrammen.
Der Wert hängt vom aktuellen Zustand des Kontexts ab, vor allem von ctx.font, aber auch von letterSpacing, wordSpacing, fontKerning und fontStretch. Die Schriftart muss vor dem Messen gesetzt werden. Die Vorschubbreite ist nicht dasselbe wie die tatsächlich eingefärbte Fläche: Kursive oder überhängende Glyphen können darüber hinausragen. Für die exakte Pixel-Ausdehnung nimmt man actualBoundingBoxLeft + actualBoundingBoxRight.
Rückgabewert
0 bei leerem String).Beispiele
Textbreite messen
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.font = '16px sans-serif';
const metrics = ctx.measureText('Hallo Welt');
console.log(metrics.width.toFixed(2));
Label mit passender Hintergrund-Box zeichnen
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
const drawLabel = (text, x, y, padding = 6) => {
ctx.font = 'bold 14px system-ui';
const { width } = ctx.measureText(text);
const height = 14;
ctx.fillStyle = '#1e293b';
ctx.fillRect(x, y - height - padding, width + padding * 2, height + padding * 2);
ctx.fillStyle = '#fff';
ctx.textBaseline = 'alphabetic';
ctx.fillText(text, x + padding, y);
};
drawLabel('Umsatz: 12.400 €', 20, 40);
Automatischer Zeilenumbruch im Canvas
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.createElement('canvas').getContext('2d');
ctx.font = '16px serif';
const lines = wrapText(ctx, 'Canvas kennt keinen automatischen Zeilenumbruch, also bauen wir ihn selbst.', 180);
lines.forEach((l, i) => ctx.fillText(l, 10, 20 + i * 20));
console.log(lines.length);
Text mit Auslassungspunkten kürzen
const truncate = (ctx, text, maxWidth) => {
if (ctx.measureText(text).width <= maxWidth) return text;
let result = text;
while (result.length && ctx.measureText(result + '…').width > maxWidth) {
result = result.slice(0, -1);
}
return result + '…';
};
const ctx = document.createElement('canvas').getContext('2d');
ctx.font = '14px sans-serif';
console.log(truncate(ctx, 'Sehr langer Dateiname_final_v2.pdf', 120));
// Wichtig · Fallstricke
- Reihenfolge beachten:
ctx.font(und ggf.letterSpacing) muss vormeasureText()gesetzt werden. Das Objekt ist eine Momentaufnahme und aktualisiert sich bei späteren Änderungen nicht. - Webfonts: Ist eine per
@font-faceeingebundene Schrift noch nicht geladen, wird mit der Ersatzschrift gemessen. Vorher mitawait document.fonts.load('16px MeineSchrift')bzw.document.fonts.readywarten. - Vorschubbreite ≠ sichtbare Breite: Bei kursiven Schriften oder Glyphen mit Überhang ist
actualBoundingBoxLeft + actualBoundingBoxRightgenauer. - Keine Transformation:
scale(),setTransform()unddevicePixelRatiofließen nicht ein; der Wert ist immer in CSS-Pixeln des Kontext-Koordinatensystems. - Performance:
measureText()in engen Schleifen (z. B. zeichenweises Kürzen) kann teuer sein – Ergebnisse cachen oder binär suchen. - Kompatibilität:
widthwird von allen Browsern seit Langem unterstützt, auch inOffscreenCanvasund Web Workern. Die übrigenTextMetrics-Felder (Bounding Boxes) sind neuer. - Die Eigenschaft ist schreibgeschützt; eine Zuweisung wird ignoriert (im Strict Mode
TypeError).