
The needle gauge
Counters, Physics, SVG
NewFree
A pad to sign or sketch on, in the minimal style, with a lazy brush: the ink does not come from the hand but from a vermilion nib tied to the hand by a thin thread. While the thread is slack the nib stays put; taut, it tows the nib behind it, and the line comes out smooth even if the hand shakes. Undo makes the nib reel its last line back in, Clear pulls every line tight like a thread until it lies straight and slips away, and a slider changes the length of the thread.
A folder that runs on its own: index.html, style.css, script.js and the libraries from a CDN. The React and Vue tabs hold the same demo as a ready component, which switches its animations off when it leaves the page.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>The leashed nib</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/roboto-flex@5.3.0/full.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- a pad to sign or sketch on with a lazy brush: the ink does not come from the hand but from a nib tied to it by a
thread of fixed length. While the thread is slack the nib stays put; pulled taut, it tows the nib, and the line
comes out smooth however the hand shakes. Undo makes the nib reel its last line back in, Clear pulls every line
tight like a thread until it lies straight and slips away, and the slider sets the length of the thread -->
<section class="sheet" aria-labelledby="sheet-title" data-card data-autoclic>
<header class="sheet__head">
<h2 class="sheet__title" id="sheet-title">Sign for your parcel</h2>
<div class="sheet__acts">
<button class="act" type="button" data-undo disabled><span class="act__word">Undo</span></button>
<button class="act" type="button" data-clear disabled><span class="act__word">Clear</span></button>
</div>
</header>
<div class="pad" tabindex="0" role="application" aria-roledescription="signature pad" aria-label="Signature pad, empty" aria-describedby="pad-help" data-pad>
<canvas class="pad__ink" aria-hidden="true" data-canvas></canvas>
<svg class="pad__over" aria-hidden="true" focusable="false" data-over>
<rect class="pad__frame" pathLength="1" data-frame></rect>
<line class="pad__base" pathLength="1" data-base></line>
<g class="dim" data-dim>
<line class="dim__end" data-dim-a></line>
<line class="dim__end" data-dim-b></line>
</g>
<path class="leash" data-leash></path>
<g class="hand" data-hand>
<line x1="-5.5" y1="0" x2="5.5" y2="0"></line>
<line x1="0" y1="-5.5" x2="0" y2="5.5"></line>
</g>
<g class="nib" data-nib>
<rect class="nib__shape" x="-3.6" y="-3.6" width="7.2" height="7.2" data-nib-shape></rect>
</g>
</svg>
<span class="pad__hint" data-hint>Sign above the line</span>
</div>
<div class="sheet__foot">
<label class="leash-word" for="leash-range"><span data-word>Leash</span></label>
<div class="range-wrap">
<input class="range" id="leash-range" type="range" min="0" max="60" step="1" value="22" data-range>
<span class="range__ticks" aria-hidden="true" data-ticks></span>
</div>
<output class="leash-val" for="leash-range" data-val>22 px</output>
</div>
<p class="sr" id="pad-help">Draw with a mouse, a pen or a finger. With the keys, the arrows move the hand, Space puts the nib down and lifts it.</p>
<p class="sr" aria-live="polite" data-live></p>
</section>
</main>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
<script src="script.js"></script>
</body>
</html>Change values, colours and text with the controls and watch the animation respond live. Or write in the code yourself. Then download the folder with your changes.
21 values to change
With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:
Take “The leashed nib” from Animorio and fit it into my siteThe hand (the mouse, the pen, the finger, the keys) and the nib are two different points. At every move the distance between them is measured: if it is less than the length of the thread the nib stays where it is; if it is more, the nib is brought along the line towards the hand, exactly a thread away. That is the whole trick: the nib only travels the long part of the movement, and shakes shorter than the thread are lost. For a quick stroke the points the browser gathers between two frames are used too (getCoalescedEvents).
The thread you see is a chain of 16 links moved with Verlet (each link remembers where it was, and the difference is its speed) with a little gravity, SAG, and then held to its length: a thread does not stretch, so every link too far from its neighbour is brought closer, 14 times a step, never pushed away. Its ends are the hand and the nib. Taut, the thread is drawn dead straight and its colour goes from grey to the black of the ink; the nib, a diamond, turns to where the thread pulls it.
Every stroke is a list of the nib’s points with their widths: the speed of the nib between two points takes the width from WIDTH[1] towards WIDTH[0] as it nears SPEED, a little at a time. It is drawn on a canvas at the screen’s density, with curves through the middle points, each piece as wide as its ends; every stroke remembers which part of it shows (from a to b, even halfway between two points), so Undo and Clear can shorten it from either end.
Undo takes the visible end of the last stroke back to its start with power2.inOut, in a time that grows with the length; the nib always sits on that end, and the far end of the thread is put on the stroke itself, a thread’s length further back, measured along the curve: it looks like a hand pulling the nib backwards along its own way. Past the start the thread goes on straight in the direction of the first piece.
Every stroke is resampled into evenly spaced points, and how far each point strays from the straight line between the two ends is broken into waves (a discrete sine transform). Then every wave k dies away as exp(−k² τ), with τ growing with time: it is the heat equation, the one that smooths a curve, which is why the small curls vanish at once and the big bends last. Straight, the stroke rings once (a damped sine of a couple of pixels) and slips away towards its end, the last stroke first, staggered.
The pad takes the focus: the arrows move the hand by 8 pixels (24 with Shift), Space or Enter put the nib down and lift it, Escape lifts it; the staircase of the keys turns into a curve by itself, thanks to the thread. The slider is a real range input: the word Leash takes its width (the wdth axis of Roboto Flex, from 40 to 151) from the length, with back.out. A click from a script (the library’s preview) signs with a pretend hand that shakes, lets the thread out and underlines in a zigzag, then does Undo, puts the thread back and does Clear.
| Name | File | Default | What it changes |
|---|---|---|---|
LEASH | script.js | 22 | The length of the thread between the hand and the nib, in pixels, the one the slider starts at: 0 draws from the hand. |
LEASH_MAX | script.js | 60 | The longest thread the slider gives, in pixels. |
WIDTH | script.js | [0.9, 2] | The thinnest and the thickest the ink gets, in pixels: fast is thin. |
SPEED | script.js | 1.3 | The speed of the nib, in pixels a millisecond, at which the ink is at its thinnest. |
SAG | script.js | 520 | How much the thread hangs when slack: its gravity, in pixels a second squared. |
REWIND | script.js | 1 | How slowly Undo reels the last stroke back in (1 means 0.4 to 1 second, by its length). |
UNTANGLE | script.js | 0.85 | The seconds Clear takes to pull a stroke straight. |
For signing for a delivery, a contract, a consent form or an accepted quote, above all with a finger or a mouse, which shake; for a sketch pad inside a creative or note-taking app, where a calm line matters more than a faithful one.
You sign with a finger without scrolling the page (touch-action none on the pad): the nib comes to where the finger lands and the thread lets out from there as the finger moves, so the nib stays out from under the fingertip and the line shows as it is made. Lifting the finger, the thread reels back in. At 390 pixels the preview’s signature has fewer loops, so it fits the pad.
The nib follows the hand on its thread, because that is how it draws, but the thread is always straight, with no swinging or hanging; Undo and Clear fade the strokes away instead of reeling them in and pulling them, the nib goes home without travelling, the pad appears without drawing itself and the word Leash changes width without the bounce.
GSAP 3.15.0, Roboto Flex (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 15 KB; the libraries: GSAP 28 KB.
Tested on 16 October 2026
Use it in your own projects and in your clients’ projects. Do not resell it or redistribute it as is. GSAP stays under its own Standard license. Full license.
With your account’s email and password.
or with your email
You’re signed in as .
With your account, you can download the zip of every animation and every pack, for free.