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 tmAscent
und tmDescent
zurü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-block
damit ich seinen vertical-align
Stil festlegen und dann herausfinden kann, wo der Browser es abgelegt hat.
So erhalten Sie ein Objekt mit zurück ascent
, descent
und height
(was gerade ist ascent
+ der descent
Einfachheit 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');