Mi piace la tua "unica idea" di fare solo una mappa statica della larghezza dei caratteri! In realtà funziona bene per i miei scopi. A volte, per motivi di prestazioni o perché non si ha un facile accesso a un DOM, è possibile che si desideri semplicemente una calcolatrice autonoma hacky rapida calibrata su un singolo carattere. Quindi eccone uno calibrato su Helvetica; passare una stringa e (facoltativamente) una dimensione del carattere:
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
}
Quella brutta matrice gigante è la larghezza dei caratteri ASCII indicizzata dal codice carattere. Quindi questo supporta solo ASCII (altrimenti assume una larghezza media dei caratteri). Fortunatamente, la larghezza si ridimensiona sostanzialmente in modo lineare con la dimensione del carattere, quindi funziona abbastanza bene con qualsiasi dimensione del carattere. È evidentemente privo di consapevolezza di crenatura, legature o altro.
Per "calibrare" ho appena eseguito il rendering di ogni carattere fino a charCode 126 (la potente tilde) su uno svg e ho ottenuto il rettangolo di selezione e l'ho salvato in questo array; più codice e spiegazione e demo qui .