¡Me gusta tu "única idea" de hacer un mapa de ancho de caracteres estático! En realidad funciona bien para mis propósitos. A veces, por razones de rendimiento o porque no tiene fácil acceso a un DOM, es posible que solo desee una calculadora independiente rápida y hacky calibrada para una sola fuente. Así que aquí hay uno calibrado para Helvetica; pasar una cadena y (opcionalmente) un tamaño de fuente:
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
}
Esa matriz fea gigante tiene anchos de caracteres ASCII indexados por código de caracteres. Por lo tanto, esto solo es compatible con ASCII (de lo contrario, supone un ancho de caracteres promedio). Afortunadamente, el ancho básicamente se escala linealmente con el tamaño de fuente, por lo que funciona bastante bien en cualquier tamaño de fuente. Es notablemente carente de conocimiento de kerning o ligaduras o lo que sea.
Para "calibrar" acabo de representar cada carácter hasta el código 126 (la poderosa tilde) en un svg y obtuve el cuadro delimitador y lo guardé en esta matriz; Más código y explicación y demostración aquí .