remix logo

Hacker Remix

The Tao of Unicode Sparklines (2021)

106 points by fanf2 10 months ago | 53 comments

sonofhans 10 months ago

This is a great hack, but it makes bad sparklines. It’s probably about as good as you can get with unicode, so props to Jon.

Sparklines have a few important properties which these do not exhibit. They’re typically higher resolution, with more data per inch. Also the slopes from point to point, and the whitespace under the typical graph/sparkline, help readability.

kqr 10 months ago

One can use Braille characters to get slightly more negative space and horizontal resolution, at the cost of vertical resolution. (They are 2×4 blocks IIRC.)

Am4TIfIsER0ppos 10 months ago

If anyone want to see an example of graphing use the braille characters (I think) look at btop https://github.com/aristocratos/btop

Speaking of misaligned characters: an upgrade a few months back in some thing (font, terminal, or renderer) caused the characters to be shifted up or down one pixel so the bottom and top now touch between lines

FujiApple 10 months ago

I recently had to look at the implementation of the Sparkline [1] widget in Ratatui which uses a similar Unicode technique but scales nicely for sparklines with larger vertical size.

[1] https://github.com/ratatui/ratatui/blob/20c88aaa5b9eb011a522...

layer8 10 months ago

Maybe we need terminal escape codes to temporarily switch to linked alternative fonts. ;)

hnlmorg 10 months ago

There are already several escape sequences for doing just this. In fact the original way of drawing terminal graphics was using a 7bit escape sequence to switch to a terminal graphics font.

Personally I’d rather see in-lined vector graphics become better supported. This was available on some of the Techtonix (iirc) hardware VTs and as far as I know, the only widespread terminal emulator to support that particular mode is xterm.

layer8 10 months ago

Isn't that more like switching to a different character set, with supporting fonts having to be already present? Or what are you referring to?

I was thinking along the lines of online (or inline) fonts, similar to web fonts in CSS, which would allow for arbitrary custom glyphs.

LukeShu 10 months ago

Sixel graphics on the vt220 (1983) worked by defining a custom font of 10x10 px characters (9x10 in high-resolution mode), which you could then switch to for any given character.

As far as I know, there is no terminal emulator that supports this flavor if sixel graphics.

estebank 10 months ago

Congratulations on reinventing sixels. :)

hnlmorg 10 months ago

Sixel is different. It’s a way of drawing graphics rather than switching to alternative character sets.

Sixels could be used here too, but native support for vector graphics would be nicer.

I’m also of the opinion that sixel sucks as a modern option. It’s got a low DPI resolution, cannot be compressed, and is its own bespoke specification which means lots of additional work for terminal maintainers. Which is why most terms these days go with their own escape sequences for natively supporting common formats like PNG and JPEG.

In my own terminal emulator, I’ve got support for several image formats but I doubt I’ll ever bother with sixel.

throw0101d 10 months ago

Meta: for the old fogies out there, Jon Udell used to write for BYTE back in the day:

* https://en.wikipedia.org/wiki/Jon_Udell

He stood up their first web site in 1995:

> One day this spring, an HTTP request popped out the back of my old Swan 386/25, rattled through our LAN, jumped across an X.25 link to BIX, negotiated its way through three major carriers and a dozen hosts, and made a final hop over a PPP link to its rendezvous with BYTE's newborn Web server, an Alpha AXP 150 located just 2 feet from the Swan.

* https://web.archive.org/web/19990128182622/http://www.byte.c...

* https://twitter.com/judell/status/1278883833903898624

* https://vintageapple.org/byte/pdf/199507_Byte_Magazine_Vol_2...

pphysch 10 months ago

Beyond Unicode, it should be possible to define a Web Component that generates SVG on-the-fly from a datasource.

Imagine:

    <sparkline src="an image or csv"\>
One cool thing about SVG is it can inherit styles from your application, so you can produce e.g. dark-mode aware graphics rather easily, also one of the perks of this Unicode approach.

nick-of-time 10 months ago

People have done something like this. No standard web component so far unfortunately. https://alexplescan.com/posts/2023/07/08/easy-svg-sparklines...

TheRealPomax 10 months ago

This would be 5 minutes work. A whole 10 if we want to respond to attribute changes in a cleanish way: https://jsbin.com/rumakulido/1/edit?html,css,js,output

TheRealPomax 10 months ago

Although of course, we don't even need a custom element here, this already has a pure-CSS solution: https://jsbin.com/xuwicoquwo/edit?html,css,js,output

pphysch 10 months ago

Nice. A real SVG sparkline would use polyline or path, though. Not much point in using Unicode glyphs.

TheRealPomax 10 months ago

Eh, you'd probably use <rect> rather than a single <path>, because then you can trivially slice your sparkline and tag every tick with metadata. So for simple sparklines you don't really need a custom element. Page elements already follow a box model, just CSS them boxes =)

But for an annotated data set that renders as a sparkline, a custom element with an SVG shadow DOM probably makes sense. Definitely more work than the "this'll do for most folks" solution though =D

nsfmc 10 months ago

the unicode angle is great for moving sparklines back into the terminal especially making it into a postgres function, since it makes so much ad-hoc analysis easier at the point of query.

it also solves the problem where sparklines feel useful to somebody reading a summary and not so useful to somebody that's just exploring data "in the moment." having it be available in postgres is brilliant.

a bit of shameless self promotion, i had done something similar ages ago but with a custom webfont and some small js to handle scaling of the input dataset, solving the problem of unicode graph characters not being baseline aligned well. http://nsfmc.github.io/chartjunk/ (turns into dust while looking at the last commit date)

Tomte 10 months ago

It‘s unfortunate that the fill blocks seem to dip below the baseline. It looks untidy.

rbanffy 10 months ago

It really depends on the font choice and terminal engine. Some terminals (such as VTE, which is the base for most Gnome terminals) renders blocks and boxes without using a font, which makes them perfectly fit the character cell.

With Unicode 16, which is coming out very shortly, there will be 2x4 mosaics (originally identified on Kaypro CP/M machines), which have about half the vertical resolution of the blocks, but twice the time resolution (and allows us to leave Braille for what it was intended for).

After this post came out, Unicode 13 introduced Teletext 2x3 mosaics and their "smoothed" versions (with diagonal lines). Those are also useful for sparklines.

divbzero 10 months ago

OP discusses the below-the-baseline issue describes it as “annoying but not a deal breaker”.

If this is a deal breaker because you’re aspiring for Edward Tufte levels of visualization purity, OP also offers an alternative that omits below-the-baseline U+2584 and U+2588. The trade off is having fewer unequally sized buckets for the data.

(Could there be font faces without this rendering issue?)

divbzero 10 months ago

> (Could there be font faces without this rendering issue?)

A comment under OP suggests that the rendering issue is font-dependent. When I view a Unicode sparkline on a test page [1], the rendering issue occurs using Arial, Courier New, Gill Sans, Helvetica, or Times New Roman, but appears to be fixed if I use Georgia, Menlo, or Comic Sans.

[1]: https://rosettacode.org/wiki/Sparkline_in_unicode

uj8efdjkfdshf 10 months ago

If you're going to pick a font to avoid this issue you might as well as define your own custom sparkline font with fancy ligatures.

divbzero 10 months ago

That’s a very interesting idea. Apparently, someone has actually tried this [1] and it looks pretty good [2].

[1]: https://github.com/aftertheflood/sparks

[2]: https://observablehq.com/@tomgp/after-the-flood-i-sparks-i-t...

Gare 10 months ago

On (mobile) Firefox they don't. And all are of equal width.

TheRealPomax 10 months ago

That depends entirely on the font used.

boffinAudio 10 months ago

As a fan of Sparklines (and Tufte in general), I have to shout out to one of my favourite places that sparklines have been used - in sudara's Audio Sparkline library for the popular JUCE Audio processing framework:

https://github.com/sudara/melatonin_audio_sparklines

The reason this is such a nerd tickle, is that sudara even went as far as to teach lldb how to render arrays' using sparklines, meaning one can get a pretty useful clue about the contents of an audio buffer within the debugger:

https://forum.juce.com/t/new-audio-sparklines-module/46606

This, to me, aligns very much with the "Tao" of sparklines - although of course I've modified my local copy to use unicode fonts, which is either heinous or fabulous, depending on how much coffee I've had before I have to hit up lldb for details about why my day is going to be good/bad... ;)

Izkata 10 months ago

FULL BLOCK is slightly shorter than LOWER SEVEN EIGHTHS BLOCK for me. They would be the same height except LOWER SEVEN EIGHTHS BLOCK has some antialiasing that extends a tiny bit higher while FULL BLOCK is a solid edge.

Also none of them drop below the baseline in the main page text, only in the code block.

(Firefox on Ubuntu 20.04)

AceJohnny2 10 months ago

(Safari 17 on MacOS 14) FULL BLOCK is the largest to me, but also dips below the line by about as much as it is above LOWER SEVEN EIGTHS BLOCK.

And unlike the author, LOWER HALF BLOCK (U+2584) does not dip below the line.

Aah, multi-platform font rendering... ;)

TheRealPomax 10 months ago

Digital typefaces are fun! Because whether they render sensibly is 100% a font issue.

willm 10 months ago

I'd be remiss if I didn't share this...

https://textual.textualize.io/widgets/sparkline/

knlb 10 months ago

I have a small python (hy) package which extends the idea to horizon charts https://github.com/kunalb/orphism

rurban 10 months ago

I once had a bash script to produce such horizontal spark lines from numeric input, but I forgot it's name. Anyone remembers it? From about the same time. As described here: https://rosettacode.org/wiki/Sparkline_in_unicode

rkharsan64 10 months ago

There's also this font that uses OpenType Contextual Alternates to create sparklines from text: https://aftertheflood.com/journal/the-worlds-first-code-free...

boffinAudio 10 months ago

Alas, the .zip file containing those fonts is no longer accessible.

Along similar lines, the absolutely delightful FF Chartwell has sparkline capabilities, plus a lot, lot more to boot (and it actually predates After-the-Floods attempt by half a decade):

https://www.vectrotype.com/chartwell

quink 10 months ago

🬼🭈🭆🭑🬽🭋🭎🭆🬹🭑🭄🭎🬭🭆🬿🭊

Teletext in Unicode - each character is three pixels tall, two pixels wide, with separate characters for inverse as well, and diagonals to get you from one set to another.

https://en.wikipedia.org/wiki/Teletext_character_set#Graphic...

Intended for use with teletext graphics, but hey, do a sparkline with them, why not? Sure, it'll only do you four levels, but do you really need more than that in this use case?

Previously on Hacker News: https://news.ycombinator.com/item?id=40269606

quink 10 months ago

Actually... they're not meant to have gaps between these lines, so: (never mind, Hacker News stripped some characters, probably because of non-BMP things, it looks like, but imagine the above on subsequent lines without a gap)

ggm 10 months ago

Why would you call a histogram a line?

If you segment your data into buckets, its a histogram.

Histospark? SparkGram?

zamadatix 10 months ago

By that argument any shaded line chart which is rasterized becomes a histogram by way of each column of pixels being a bar :p. (i.e. the "binning" is just the horizontal resolution of the rasterization, not a choice in abandoning the intent of showing a line).

ggm 10 months ago

Eh. if you set out to chart and the system rasterises or dithers, its a line.

If you set out to divide your data into buckets and hand-select the elements to represent the slope of the trend from a set of 8.. It's ..

WalterBright 10 months ago

More Unicode mission creep. What's next, 4 characters that form 90 degree line segments, so you can write a circle? If you want images, use gifs. Grump grump grump.

Joker_vD 10 months ago

This is a hillarious complaint because ◯, ◜, ◝, ◞, ◟, ◠, and ◡ has been around since Unicode 1.1 of 1993.

WalterBright 10 months ago

Just shoot me now. I demand that you shoot me now.

egypturnash 10 months ago

Is it Walter season then?

cryptonector 10 months ago

Upvote for the grump thing, but really, Unicode is about scripts, and scripts are evolving. If we want to write sparklines, we get to with pen and paper, but then... we can't transliterate them into Unicode? That makes no sense. No, characters for sparklines make a lot of sense, more than for emojis, but when you consider that CJK characters are basically monochrome stylized emojis, modern emojis make sense too.

My biggest gripe here is that we will need to kill UTF-16 so we can have a larger set of codepoints, and that's only a gripe because killing UTF-16 is going to be really difficult, not because I want to keep UTF-16 (oh no, UTF-16 really needs to die).

samatman 10 months ago

That's uh. I dunno how to tell ya this Walter.

Coming your way in Unicode 16.0...

Allow me to introduce: BOTTOM LEFT JUSTIFIED UPPER RIGHT QUARTER BLACK CIRCLE!

https://www.unicode.org/charts/PDF/Unicode-16.0/U160-1FB00.p...

But wait! There's more! U+1CC31, UPPER CENTRE LEFT TWELFTH CIRCLE! And you best believe there's 11 more.

https://www.unicode.org/charts/PDF/Unicode-16.0/U160-1CC00.p...

Joker_vD 10 months ago

I personally like getting more terminal-oriented ideographical symbols in the Unicode; what I don't like is yet another font variation for the basic Latin alphabet. Oh well.

zamadatix 10 months ago

I think there comes a point we should just embrace sixels so you can draw whatever it is you want to be shown in a character cell. That point is usually somewhere around here where it's "sure, I can copy it as normal text data but is it actually going to look like anything like it's supposed in a normal font anyways?". Even Windows is getting support for sixels now.

WalterBright 10 months ago

gag me with a spoon

boffinAudio 10 months ago

Hey Walter, characters are images. ;)

WalterBright 10 months ago

I know you're joking, but the alphabet shapes actually started out as pictograms. The "A" is an upside down ram's head.

boffinAudio 10 months ago

I mean, I wasn't really joking - because yes, pictograms are images too. Isn't it the case that pretty much every device we see, is an image? I'm being 'smart-ass' about it, but I do think there is some use case where, eventually, its all just pictures, all the way down ..

I, for one, would love to see a UI that is composed entirely of typographic symbology, even to the point that it would function beyond the normal UI paradigms. I'm a huge fan of things like FF Chartwell, where the font contains super rich, detailed information that is not just a 'letter' or 'character' .. See https://news.ycombinator.com/item?id=41365761 if you don't know what FF Chartwell is yet, maybe you'll enjoy it, maybe not ..

10 months ago