A 10x faster and more accurate text wrapping util in < 2KB (min) (MIT Licensed)
uWrap exists to efficiently predict varying row heights for list and grid virtualization, a technique for UI performance optimization when rendering large, scrollable datasets.
Doing this both quickly and accurately turns out to be a non-trivial task since Canvas2D provides no API for text wrapping, and measureText()
is quite expensive;
measuring via DOM is also a non-starter due to poor performance.
Additionally, font size, variable-width kerning, letter-spacing
, explicit line breaks, and different white-space
choices affect the number of wrapped lines.
Notes:
- Today, works most accurately with Latin charsets
- Does not yet handle Windows-style
rn
explicit line breaks - Only
pre-line
wrapping strategy is implemented so far
uWrap handily out-performs canvas-hypertxt in both CPU and memory usage by a wide margin while being significantly more accurate.
The benchmark below wraps 100,000 random sentences in boxes of random widths between 50px and 250px.
You can see this live in DevTools console of the demo page.
or
<script src="./dist/uWrap.iife.min.js">script>
A 10 LoC uWrap.d.ts TypeScript def.
// impor
5 Comments
Jaxkr
Hi OP! Thanks for sharing.
I don’t totally understand the point of this. Why would you want to use a Canvas renderer for this use case? If you want to render a massive table, apps will render a subset of it on regular HTML elements like EveryUUID [1].
1: https://news.ycombinator.com/item?id=42342382
ForOldHack
Any underlying dependencies we need to know about?
somishere
I can count on one hand the number of times I've needed something like this in the last decade. But I'd also need to count the same number of times I've implemented a less than ideal solution that's ended up in prod. Great work!
noduerme
I remember getting so deep in the weeds doing this kind of thing in responsively-resized Flash sites, a challenge similar to doing it in canvas. But what at that time I was trying to do (and what I'd really love to see now) was to reproduce runaround text the way you would have it in Quark or Pagemaker (or that newer Adobe program). Justifiable text flow within an arbitrary closed path shape, so you could have multi-column text with adjustable gutters, running with curved borders around scaling embedded graphics. My solutions for that involved a lot of setup/tear-down of invisible text fields relying on native text handling, line by line or paragraph by paragraph, then a lot of remeasuring, and then a lot of optimization to make it more performant. I wrote a similar set of code for handling text in generated PDF files.
As an old school print designer, I would love to see a return to a web with multi-column text on desktop, that reformatted to single column on mobile, and graphics runarounds much more complicated in shape than what a float can do. The art of typographic layout has been lost on the web, because those things are hard. An OS general-purpose engine that could handle layouts like that in any screen size, on Canvas or using absolute positioned divs or generating PDFs, would go a long way toward restoring artistic originality in the "layouting" of online publications.
tejasm_
[dead]