To approximate the width of strings without touching the DOM. (Or rather: getBoundingClientRect is used to calibrate a static function.) Choose a font-family upfront; font-size can be passed as a parameter.
Calibration script seems to suck in Firefox… but the generated calibrated function should work fine in Firefox!
function measureText(string, 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 string
.split('')
.map(c => c.charCodeAt(0) < widths.length ? widths[c.charCodeAt(0)] : avg)
.reduce((cur, acc) => acc + cur) * fontSize
}
So we have this chart in React and we want the right axis to autosize to fit labels of varying length. One solution is to render the whole axis, get its bounding box, and then re-render the whole chart with the computer axis width as a margin parameter. But that sorta sucks because you double your render cycles (or fracture your render code in weird unreadable ways, with un-React-like DOM manipulation).
This solution is fragile and hacky in other ways, but may be perfectly suitable in many cases: just do the math with hardcoded character widths! Sorry! The measureText function here is calibrated once to a font (by you! manually! by default, Helvetica, natch) and then takes a string and font size and returns the computed rendered width. Just copy and paste the measureText function into your project.
Obviously assumes no kerning, no ligatures, no wrapping, etc. Only supports ASCII; otherwise it assumes a default average character width. It’s also missing a lot of weird thin spaces and such.
This has surely been done a million times (including by my coworker it turns out lol), there’s stuff like adambisek/string-pixel-width, but I couldn’t quickly find something quick & easy & copypastable.
Good night.