Click, Tap, Pinch, Stitch
This article digs into the technical details of how we designed input handling for StitchPress. It's a bit like an architecture teardown. We'll keep the jargon to a minimum, so there's still something in it for you if you're not that into code or technical stuff. Think of it as a dev log: a look at how much thought and care went into designing StitchPress, an app that's all about interaction.
Every device counts
At StitchPress, we try to be as inclusive as we can about the devices we support (desktops, phones, tablets and more) and the operating systems and platforms we run on (macOS, Windows, Android, iOS and so on). To get there, we had two options:
- Write native code for every platform.
- Build on web technology, and on the one thing almost every modern device already has: the browser.
We chose the second. We simply don't have the capacity to write native code for every platform we'd like to reach. That said, the second option is no easy feat either; it's just more manageable.
Right now, StitchPress supports keyboard and mouse, as well as keyboard and trackpad, in browsers on the major desktop operating systems: Windows, macOS and Linux (Ubuntu and Arch Linux are confirmed; other distros may need more testing). Touch devices, like tablets and phones on both Android and iOS, are supported too. None of this comes out of the box with the browser. Intricate input handling, especially on an infinite canvas, takes careful software architecture and a lot of tedious fine-tuning.
Under the hood
Kinnet Studio, the small team behind StitchPress, has been building a number of web apps around the idea of an infinite canvas. Along the way, we put together a series of open-source packages called ue-too that help build infinite canvas apps, especially when it comes to how the viewport (the area of the canvas you're looking at) responds to your input. If you're a developer, feel free to take a look: the source code is on GitHub, and the packages are on npm, with @ue-too/board handling the viewport. StitchPress itself is built on ue-too.
So how does it really work?
To understand how StitchPress handles your input, we first need to talk about
the browser's event system. Every time you click a mouse button, scroll the
mouse wheel or press a key on your keyboard, the browser sends an event to the
script running on the page. But the script doesn't receive every event the
browser has to offer. It opts in to the ones it cares about by adding event
listeners, which let the browser know what it wants to hear about. So if a
script wants to know when you press the left mouse button, it listens for the
mousedown event. There are many kinds of events a script can listen to,
enough to cover every kind of input StitchPress needs.
The browser's event system is designed to be flexible, but that flexibility comes at a cost: complexity. Input events often have to be combined. Say you want people to be able to hold the spacebar and drag the mouse to pan the viewport, just like in Figma (and many other infinite canvas apps). You'd need to listen to both keyboard events and mouse events to make that happen. The hard part is that you can't simply funnel the events you want into a single listener. Each event gets its own listener, and you have to coordinate them so the pan kicks in at exactly the right moment. The more input events you need, the harder it gets to keep them all in check.
To tackle this complexity, StitchPress (which is built on top of @ue-too/board) uses something called a state machine. In simple terms, a state machine is a machine with a number of different states. Different states handle the same event differently (or don't handle it at all), and events can trigger transitions from one state to another. It's much easier to show than tell, so below is a small example of how the infinite canvas handles your input. The example draws its own input-handling state machine as a graph on the canvas itself, and the graph responds in real time: as you pan and zoom around the canvas (use the dropdown menu to pick your kind of input), you can watch the events and state transitions as they happen. The example is stripped down to the basics: panning and zooming the viewport.
StitchPress uses several state machines for various purposes, but the basics are the same. There are more advanced techniques too, like extending an existing state machine (possibly one someone else wrote). StitchPress uses those as well, but they're outside the scope of today's article. The state machine package, @ue-too/being, has a documentation site with a more detailed explanation and a guide to putting it to use. If you're interested in using a state machine in your own project, feel free to check it out.
I think this is a good place to wrap up this entry. This one may not be as relevant to crochet or the wider fiber arts community as our other posts, since it leans toward developers. But we do want you to know that user experience is a huge part of how we design StitchPress at Kinnet Studio, and we don't take it lightly.
StitchPress is currently in pre-alpha, and we're actively looking for crochet diagram designers to help shape the experience. If you're interested and we haven't reached out to you yet, email us at contact@kinnet.studio. If you'd like to follow along with the alpha and beta tests, join the waitlist: