|
1 | 1 | ## ⏎ μWrap |
2 | 2 |
|
3 | | -A [10x faster](#performance) and more accurate text wrapping util in [1.5KB (min)](https://github.com/leeoniya/uWrap/blob/main/dist/uWrap.iife.min.js) _(MIT Licensed)_ |
| 3 | +A [10x faster](#performance) and more accurate text wrapping util in [< 2KB (min)](https://github.com/leeoniya/uWrap/blob/main/dist/uWrap.iife.min.js) _(MIT Licensed)_ |
4 | 4 |
|
5 | 5 | --- |
6 | 6 | ### Introduction |
7 | 7 |
|
8 | | -uWrap was made to efficiently predict varying row heights for list and grid [virtualization](https://www.patterns.dev/vanilla/virtual-lists/) - a strategy for performance optimization when rendering large datasets. |
9 | | -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 very expensive; |
10 | | -rendering to the DOM is also out of the question due to poor performance. |
11 | | -Additionally, font size, variable-width fonts, `letter-spacing`, explicit line breaks, and different `white-space` choices impact the exact number of lines in final result. |
| 8 | +uWrap exists to efficiently predict varying row heights for list and grid [virtualization](https://www.patterns.dev/vanilla/virtual-lists/), a technique for UI performance optimization when rendering large, scrollable datasets. |
| 9 | +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; |
| 10 | +measuring via DOM is also a non-starter due to poor performance. |
| 11 | +Additionally, font size, variable-width fonts, `letter-spacing`, explicit line breaks, and different `white-space` choices affect the number of wrapped lines. |
| 12 | + |
| 13 | +Notes: |
| 14 | + |
| 15 | +- Today, works most accurately with Latin charsets |
| 16 | +- Does not yet handle Windows-style `\r\n` explicit line breaks |
| 17 | +- Only `pre-line` wrapping strategy is implemented so far |
12 | 18 |
|
13 | 19 | --- |
14 | 20 | ### Performance |
15 | 21 |
|
16 | | -[canvas-hypertxt](https://github.com/glideapps/canvas-hypertxt) looks to be the fastest similar utility. |
17 | | -uWrap handily out-performs it in both CPU and memory usage by a wide margin while being significantly _more_ accurate. |
| 22 | +uWrap handily out-performs [canvas-hypertxt](https://github.com/glideapps/canvas-hypertxt) in both CPU and memory usage by a wide margin while being significantly _more_ accurate. |
18 | 23 |
|
19 | | -The benchmark below wraps 100k random sentances within boxes of random widths between 50px and 250px. |
20 | | -You can see this benchmark performed in the console on the [demo page](https://leeoniya.github.io/uWrap/demo/). |
| 24 | +The benchmark below wraps 100k random sentances in boxes of random widths between 50px and 250px. |
| 25 | +You can see this live in DevTools console of the [demo page](https://leeoniya.github.io/uWrap/demo/). |
21 | 26 |
|
22 | 27 | <table> |
23 | 28 | <tr> |
@@ -70,18 +75,18 @@ let ctx = document.createElement('canvas').getContext('2d'); |
70 | 75 | ctx.font = "14px Inter, sans-serif"; |
71 | 76 | ctx.letterSpacing = '0.15px'; |
72 | 77 |
|
73 | | -// init wrapper |
74 | | -let wrap = varPreLine(ctx); |
| 78 | +// init util fns |
| 79 | +const { count, test, split } = varPreLine(ctx); |
75 | 80 |
|
76 | | -// sample text |
| 81 | +// example text |
77 | 82 | let text = 'The quick brown fox jumps over the lazy dog.'; |
78 | 83 |
|
79 | | -// call wrapper with text to wrap, width of bounding container, and per-line callback |
80 | | -let lineCount = 0; |
81 | | -wrap(text, width, () => { count++; }); |
| 84 | +// count lines |
| 85 | +let numLines = count(text, width); |
82 | 86 |
|
83 | | -// or process the lines for rendering, etc.. |
| 87 | +// test if text will wrap |
| 88 | +let willWrap = test(text, width); |
84 | 89 |
|
85 | | -let lines = []; |
86 | | -wrap(text, width, (idx0, idx1) => { lines.push(text.slice(idx0, idx1)); }); |
| 90 | +// split lines (with optional limit) |
| 91 | +let lines = split(text, width, 3); |
87 | 92 | ``` |
0 commit comments