UPDATE - Als Beispiel für diese Arbeit habe ich diese Technik im Carota-Editor verwendet .
Im Anschluss an ellisbben Antwort, hier ist eine erweiterte Version den Auf- und Abstieg von der Basislinie zu erhalten, dh gleiche wie tmAscentund tmDescentzurückgegeben von Win32 GetTextMetric API. Dies ist erforderlich, wenn Sie einen Textlauf mit Zeilenumbrüchen in verschiedenen Schriftarten / Größen ausführen möchten.

Das obige Bild wurde in Safari auf einer Leinwand generiert, wobei Rot die oberste Zeile ist, in der die Leinwand den Text zeichnen soll, Grün die Grundlinie und Blau die Unterseite (also Rot bis Blau ist die volle Höhe).
Verwenden von jQuery für Prägnanz:
var getTextHeight = function(font) {
var text = $('<span>Hg</span>').css({ fontFamily: font });
var block = $('<div style="display: inline-block; width: 1px; height: 0px;"></div>');
var div = $('<div></div>');
div.append(text, block);
var body = $('body');
body.append(div);
try {
var result = {};
block.css({ verticalAlign: 'baseline' });
result.ascent = block.offset().top - text.offset().top;
block.css({ verticalAlign: 'bottom' });
result.height = block.offset().top - text.offset().top;
result.descent = result.height - result.ascent;
} finally {
div.remove();
}
return result;
};
Zusätzlich zu einem Textelement füge ich ein div hinzu, display: inline-blockdamit ich seinen vertical-alignStil festlegen und dann herausfinden kann, wo der Browser es abgelegt hat.
So erhalten Sie ein Objekt mit zurück ascent, descentund height(was gerade ist ascent+ der descentEinfachheit halber). Um es zu testen, lohnt es sich, eine Funktion zu haben, die eine horizontale Linie zeichnet:
var testLine = function(ctx, x, y, len, style) {
ctx.strokeStyle = style;
ctx.beginPath();
ctx.moveTo(x, y);
ctx.lineTo(x + len, y);
ctx.closePath();
ctx.stroke();
};
Dann können Sie sehen, wie der Text relativ zur Ober-, Grundlinie und Unterseite auf der Leinwand positioniert ist:
var font = '36pt Times';
var message = 'Big Text';
ctx.fillStyle = 'black';
ctx.textAlign = 'left';
ctx.textBaseline = 'top'; // important!
ctx.font = font;
ctx.fillText(message, x, y);
// Canvas can tell us the width
var w = ctx.measureText(message).width;
// New function gets the other info we need
var h = getTextHeight(font);
testLine(ctx, x, y, w, 'red');
testLine(ctx, x, y + h.ascent, w, 'green');
testLine(ctx, x, y + h.height, w, 'blue');