Ich mag deine "einzige Idee", einfach eine statische Zeichenkarte zu erstellen! Es funktioniert tatsächlich gut für meine Zwecke. Manchmal, aus Gründen der Leistung oder weil Sie keinen einfachen Zugang zu einem DOM haben, können Sie nur eine schnelle hacky Standalone-Rechner kalibriert, um eine einzelne Schriftart wollen. Hier ist also einer, der auf Helvetica kalibriert ist; übergeben Sie eine Zeichenkette und eine Schriftgröße:
const widths = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2796875,0.2765625,0.3546875,0.5546875,0.5546875,0.8890625,0.665625,0.190625,0.3328125,0.3328125,0.3890625,0.5828125,0.2765625,0.3328125,0.2765625,0.3015625,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.2765625,0.2765625,0.584375,0.5828125,0.584375,0.5546875,1.0140625,0.665625,0.665625,0.721875,0.721875,0.665625,0.609375,0.7765625,0.721875,0.2765625,0.5,0.665625,0.5546875,0.8328125,0.721875,0.7765625,0.665625,0.7765625,0.721875,0.665625,0.609375,0.721875,0.665625,0.94375,0.665625,0.665625,0.609375,0.2765625,0.3546875,0.2765625,0.4765625,0.5546875,0.3328125,0.5546875,0.5546875,0.5,0.5546875,0.5546875,0.2765625,0.5546875,0.5546875,0.221875,0.240625,0.5,0.221875,0.8328125,0.5546875,0.5546875,0.5546875,0.5546875,0.3328125,0.5,0.2765625,0.5546875,0.5,0.721875,0.5,0.5,0.5,0.3546875,0.259375,0.353125,0.5890625]
const avg = 0.5279276315789471
function measureText(str, fontSize) {
return Array.from(str).reduce(
(acc, cur) => acc + (widths[cur.charCodeAt(0)] ?? avg), 0
) * fontSize
}
Dieses riesige hässliche Array besteht aus ASCII-Zeichenbreiten, die nach Zeichencode indiziert sind. Dies unterstützt also nur ASCII (ansonsten wird eine durchschnittliche Zeichenbreite angenommen). Glücklicherweise skaliert die Breite grundsätzlich linear mit der Schriftgröße, so dass es bei jeder Schriftgröße ziemlich gut funktioniert. Es ist merklich fehlt jedes Bewusstsein für Kerning oder Ligaturen oder was auch immer.
Um zu "kalibrieren", habe ich einfach jedes Zeichen bis charCode 126 (die mächtige Tilde) auf ein svg gerendert und die Bounding Box erhalten und in diesem Array gespeichert; mehr Code und Erklärung und Demo hier .