Podoba mi się twój „jedyny pomysł” zrobienia statycznej mapy szerokości postaci! W rzeczywistości działa dobrze dla moich celów. Czasami, ze względu na wydajność lub ponieważ nie masz łatwego dostępu do DOM, możesz po prostu chcieć szybkiego, samodzielnego kalkulatora skalibrowanego do pojedynczej czcionki. Oto jeden skalibrowany do Helvetica; przekazać ciąg i (opcjonalnie) rozmiar czcionki:
function measureText(str, fontSize = 10) {
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
return str
.split('')
.map(c => c.charCodeAt(0) < widths.length ? widths[c.charCodeAt(0)] : avg)
.reduce((cur, acc) => acc + cur) * fontSize
}
Ta olbrzymia brzydka tablica ma szerokość znaków ASCII indeksowaną kodem znaków. To obsługuje tylko ASCII (w przeciwnym razie zakłada średnią szerokość znaków). Na szczęście szerokość zasadniczo skaluje się liniowo z rozmiarem czcionki, więc działa całkiem dobrze przy każdym rozmiarze czcionki. Zauważalnie brakuje mu świadomości kerningu, ligatur czy czegokolwiek innego.
Aby „skalibrować” po prostu renderowałem każdą postać do charCode 126 (potężna tylda) na pliku svg, dostałem obwiednię i zapisałem ją w tej tablicy; więcej kodu, wyjaśnienia i demo tutaj .