Jamming on a 13 year old sketchy-sketch
I just posted Sticky Scribbles to Glitch as a Glitch Jam entry for August 2024. The prompt got me thinking about some old web art projects that have come and gone, so I picked one up, dusted it off, dropped it on the floor, stepped on it, cut myself on the pieces, bought expensive raw goods from the store, and rebuilt a nearly unrecognizable new version that does the same thing.
I thought I’d post the write-up on my blog, as well.
Sticky Scribbles
- Type some text and choose a font.
- Maybe scribble on the sticky note a little.
- Copy-paste the Output SVG into a file of your own choosing.
- Open it in your pen plotter software and plot it, I guess!
Need to erase? A page refresh will clear all scribbling.
The fonts are vector strokes suitable for plotting. They’re called Hershey fonts and their story is pretty interesting!
You can also find the full source and history on GitHub.
Why
Inspired by the August 2024 Glitch Jams prompt of “#justdraw”, I remembered an old project from 2011.
Back then I worked for MakerBot Industries and, at the urging of my friend Matt Griffin,
had started a descent into madnes- pen plotting. For me, that meant using the
MakerBot Unicorn a tool for the MakerBot Cupcake CNC that replaced the plastic extruder
to turn a 3D printer into a loosey-goosey pen plotter.
As with most DIY 3D printers of the day, the Cupcake CNC was driven by G-Code - short instructions sent over a serial port to tell it how to move its motors, etc. When I started playing around, the process for going from some vector artwork to G-Code was pretty labor intensive and required multiple tools.
The work area for the Cupcake CNC is 10cm square, which is just a little bit bigger than
a pad of 3"x3" name brand sticky notes. So, these easily becamie a target for my madnes making.
In February of that year I particpated in “Thing-a-Day” on Posterous (RIP), and worked on several projects to try and boost the ease of use of this whole ecosystem.
A timeline you didn’t ask for
Unicorn G-Code extension for Inkscape
Mashing up some example Python code from the Unicorn release, and the Inkscape driver for Evil Mad Scientist Laboratories’ EggBot, this extension let you save (simple) drawings as G-Code that you could plot using a Cupcake CNC + Unicorn.
- 2011-02-01 - Announced the Unicorn G-Code extension for Inkscape.
- GitHub repository (archived 2018)
- Thingiverse
- 2011-02-02 - Added a pen registration step and homing support
- 2011-02-03 - Added support for multiple copies and continuous plotting
- 2011-02-04 - Added support for pausing to change pens
While I made this Inkscape extension to serve a very niche machine, I ended up continuing to improve it here and there. I was surprised to see it adopted by some DIY CNC projects from all over the world!
Unfortunately, I never made much of a habit out of using my own extension, so when the extension interfaces changed for Inkscape 0.91.x, I ended up marking it read-only.
There are over 100 forks, though, so maybe somebody picked it back up!
Hershey fonts
Matt introduced me to Hershey fonts, a set of vector fonts designed for the U.S. government for use on CNC machines for plotting or engraving. These were in a somewhat legible format, so I became a little obsessed with using them for plotter projects.
- 2011-02-06 Announced conversions of the Hershey fonts to SVG
- Hershey fonts in SVG on Thingiverse
- Windell of Evil Mad Scientist Laboratories was motivated by this to make an Inkscape extenstion for rendering Hershey text. That extension became part of Inkscape and after time and improvements it’s still there!
- 2011-02-08 - Hershey font rendering as SVG with JavaScript with Raphaël.js. A little proof of concept that would eventually become this little proof-of-concept.
- 2011-02-16 - Live demo using jQuery and Raphaël.js
- 2011-02-17 - Added line wrapping to the demo
- 2011-02-20 - Replaced Raphaël.js with canvas
- 2011-02-21 - Auto-scale text to fit a box
- 2011-02-22 - Added the cursed sticky note backdrop
- 2011-02-23 - Replaced canvas with Keith Wood’s jQuery SVG plugin
- 2011-02-24 - Sized everything for plotting on a sticky note via Unicorn
- 2011-02-25 - Added terrible scribbling. Insisting on having lines visually line up with the sticky note background but come out correctly aligned in the resulting SVG was really biting me here.
- 2011-02-26 - “Improved” the terrible scribbling. (Note: this did not fix the alignment issues. Why was I trying to do all the math myself?)
I’d love to share gratuitous details about rewriting bits of this little tool. Unfortunately, I worked on it live on my site that entire time without any version control. 😭
(Where was Glitch in 2011?? lol)
Misc (un)related projects
This version
While you can find the entire history on the sticky-scribbles
GitHub,
I had a good time figuring out how I left this ~13 year old project and choosing ways to “modernize”
or at least “make it less bad to my eyes”.
Fixed the cursed sticky note projection
The drawing canvas markup can be summarized like this:
- outer
<svg>
with background image of the stick note- inner
<g>
roup with a painstakingly trial-and-erroredtransform
that made rendered Hershey text look “mostly right”<g>
roup for the actual rendered Hershey text<g>
roup for the scribbles
- inner
When we scribble onto the canvas, the pointer coordinates don’t account for that transform
, so
if we save them as-is, they’ll be skewed from where they appear on the sticky note preview.
Previously, I tried to do a bunch of math on my own, which worked out really badly.
Since then, I realized that if I have an existing transform
, I can:
- get that transform as a matrix (thx StackOverflow)
- invert that matrix
- apply that matrix to the pointer coordinate
When we add the transformed coordinate to our scribble, it now visually lines up with the preview on the sticky note! Miracle.
SVG building
The 2011 version of this demo used Jeff Wood’s jQuery SVG plugin
to rebuild pretty much the entire contents of the <svg>
any time something changed.
However, the main structure of the SVG described above doesn’t change at all! So I moved the
<g>
roups that contain the transform
to make things line up with the sticky note, and its
inner <g>
roups for the rendered Hershey text and pointer scribbles into the markup on the page.
There were still a couple of useful utilities for creating <g>
roup and <path>
elements in the
jQuery SVG plugin, so I made my own version in a little ES module svg
helper
Going vanilla
There were lots of jQuery-isms that I vanilla-ized and in many cases modernized.
- replace instances of
$('#someid')
with a singledocument.querySelector
and a variable - replace
$(someArray).each(...)
withfor (const item of someArray)
- update the
hershey.js
font parsing and rendering helper as an ES module.- Made use of
async
andPromise
s to get rid of some messysetTimeout
calls around font loading.
- Made use of
- replace all
var
declarations withlet
andconst
“Web Component” for scribbling
One of the biggest changes was extracting the handling of events and (re-)rendering out of a big spaghetti ball and into self-contained bits. I did these as web components that don’t actually manage any child HTML. Instead, their attributes tell them which elements on the page they should hook into for events or render onto.
The <svg-scribbler>
component is interesting because I have it lean more into using the DOM as
new scribbles are added.
Previously: as the user draws a new scribble, they’re pushed into an array, and on every change we basically call a “render” function that throws out the SVG contents and re-creates it.
The new component simply creates a new <path>
element when the user starts drawing and updates the
d
attribute as the user draws. When they stop drawing, the <path>
is already in the page and done.
When the user starts drawing again, we a new <path>
element is created without disturbing any
existing <path>
s from previous scribbles.
Take a look at js/svg-scribbler.js
for details.
“Web Component” for Hershey text
Similarly, the <svg-hersheytext>
component takes care of listening for changes as you type
in the <textarea>
and re-rendering the <path>
s for the text contents.
One wrinkle here is that we have a <select>
dropdown to let you select a different Hershey
font. Previously, a jQuery change
handler on the <select>
for choosing a Hershey font would load
the newly selected font and then call what amounted to a top-level “render” function to draw
all Hershey text and scribbles again.
The updated version uses a simpler event handler that emits a custom HersheyFont:updated
event.
<svg-hersheytext>
elements listen for that custom events on the window
object, and re-renders.
If you haven’t used them, I think Chris Ferdinandi does a great job explaining the how and why of custom events.
MutationObserver for SVG output area
Wrapped up in the previous spaghetti of “render-everything” style calls was a stop to generate
an SVG string and slap it in a <textarea>
.
Now that the most of the SVG stays around in the page, I’ve replaced that with a MutationObserver that kicks off whenever elements are added or changed down in the SVG tree. I love this!
Known Issues
Naive pointer*
events handling does unexpected things on multi-touch devices
For example, this two-finger drag makes kind of a zig-zaggy filled-in area instead of two distinct lines:
I think this is fun and weird, actually.
inkscape-unicorn
is deprecated!
Yeah so the tool this was designed to make drawings for isn’t really a going thing in 2024.
Um. Sorry? Enjoy your SVG scribbles anyway!