
The needle gauge
Counters, Physics, SVG
NewFree
The six boxes of a sign-in code and under them a 1960s telephone dial: put a finger in a hole and turn it to the chrome stop, then the wheel runs back by itself at the governor’s steady speed, filling one tick for every pulse, and only then the digit drops into its box. Digits typed on the keyboard dial themselves; with six digits the code is checked and the centre card says Verified.
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 rotary dial code field</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/archivo@5.3.0/wdth.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the rotary dial code field: the six boxes of a sign-in code, and under them a 1960s telephone dial in sage
enamel. A finger in a hole turns the clear wheel clockwise to the chrome stop; let go, it runs back on its own
at the governor's steady speed, one tick filling by the stop for every pulse, and the digit drops into the
next box. Typed digits dial themselves; six digits are checked and the centre card says Verified -->
<section class="rd" aria-label="Verification code" data-rd>
<!-- the boxes only show the code; the field a screen reader and the keys use is the input inside the dial -->
<div class="rd__boxes" aria-hidden="true" data-boxes></div>
<div class="rd__dial" data-dial>
<!-- three layers: the still base and number card, the finger wheel (the only part redrawn as it turns), and on
top the finger stop, the pulse ticks and the centre card -->
<svg class="rd__art" viewBox="0 0 400 400" aria-hidden="true" data-art="base"></svg>
<svg class="rd__art rd__art--wheel" viewBox="0 0 400 400" aria-hidden="true" data-art="wheel"></svg>
<svg class="rd__art rd__art--top" viewBox="0 0 400 400" aria-hidden="true" data-art="top"></svg>
<label class="sr" for="rd-code" data-label>Verification code, 6 digits</label>
<input class="rd__input sr" id="rd-code" type="text" inputmode="numeric" autocomplete="one-time-code"
spellcheck="false" aria-describedby="rd-hint" data-input>
</div>
<p class="sr" id="rd-hint">Rotary dial. Type the digits and the dial turns them for you, or put a finger in a hole
and turn it clockwise to the metal stop. Backspace removes the last digit.</p>
<div class="rd__actions">
<button class="rd__quiet rd__quiet--sms" type="button" data-sms data-autoclic>
<svg class="rd__icon" viewBox="0 0 20 20" aria-hidden="true" data-icon><path d="M4.5 3.5h11a2 2 0 0 1 2 2v6.5a2 2 0 0 1-2 2H9.2l-3.6 2.8V14H4.5a2 2 0 0 1-2-2V5.5a2 2 0 0 1 2-2z"/><path d="M6.4 7.4h7.2M6.4 10.2h4.6"/></svg>
<span>Use code from SMS</span>
</button>
<button class="rd__quiet rd__quiet--clear" type="button" aria-disabled="true" data-clear>
<svg class="rd__icon" viewBox="0 0 20 20" aria-hidden="true" data-icon><path d="M5.2 7.4a5.6 5.6 0 1 1-.8 4.8"/><path d="M4.6 3.6v4.2h4.2"/></svg>
<span>Clear</span>
</button>
</div>
<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.
40 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 rotary dial code field” from Animorio and fit it into my siteThe drawing is SVG in three stacked layers: below, the base, the well and the number card, drawn once; in the middle the wheel, the only one redrawn; on top the stop, the ticks and the card. The wheel is a single path with fill-rule evenodd (the outer circle, the inner one and the ten holes), rewritten every frame from the angle; the bevel and the shadow of each hole are a group that moves without turning, so the light stays at the top left while the wheel turns.
On pointerdown the hole under the pointer is found and the pointer is captured. At every move the angle round the centre is measured with atan2 and the difference from the last one, brought between -180 and 180, is added up, so passing six o’clock makes no jump; near the centre the angle is not read. The wheel’s angle is that sum, held between 0 and the hole’s stop: (n + 1) × 30 degrees for digit n, 330 for the 0. Reaching the stop there is a knock: the wheel bounces back 1.8 degrees and the stop turns a degree round its screw.
Let go at the stop, the wheel goes back on gsap.ticker at a constant speed (GOVERNOR degrees a second, step capped at 1/30 s), with no easing. As on a real dial it sends a pulse every 30 degrees after the first 15, and the last 45 are the pause between digits: at every pulse the next tick fills. At home a bounce of 1.3 and then 0.35 degrees, added to the angle, and the digit drops into its box with back.out. When nothing moves nothing is redrawn.
The real field is a hidden input inside the dial, with inputmode numeric and autocomplete one-time-code: digits pressed, pasted or offered by the phone go into a queue, and an automatic finger dials them. A finger value goes with sine.inOut a little past the stop, and the wheel follows it up to the stop, so it gets there still moving and the knock is felt. The way back uses AUTO_GOVERNOR, and the next digit starts while the wheel is still settling, because the bounce is added separately.
With the last digit the dial stops, a red arc runs round the card and the figures make a wave of opacity; after CHECKING seconds the boxes turn green, the card turns to VERIFIED with a tick drawn by stroke-dashoffset, and after RESET seconds the figures lift out and the field empties. An aria-live region says every step, for example “3 dialled, 4 of 6”.
| Name | File | Default | What it changes |
|---|---|---|---|
LENGTH | script.js | 6 | How many digits the code has. |
SAMPLE | script.js | '481592' | The code the Use code from SMS button dials. |
GOVERNOR | script.js | 330 | How fast the wheel runs home after a hand lets go, in degrees a second (a real dial does about 300). |
AUTO_GOVERNOR | script.js | 720 | How fast it runs home when the dial turns by itself, for typed digits and the SMS code. |
FINGER | script.js | 1000 | How fast the automatic finger turns the wheel to the stop, in degrees a second. |
HOLD | script.js | 0.06 | How many seconds the automatic finger stays against the stop. |
CHECKING | script.js | 0.8 | How many seconds the code takes to check. |
RESET | script.js | 3.8 | How many seconds it stays verified before it clears itself. |
WORD | script.js | 'DIAL' | The word printed on the centre card (a long one is set smaller). |
In the code step of a two-step sign-in, in confirming a phone number or in an invitation code, on a site with a period soul: a radio station, a 1960s bar or hotel, a mid-century furniture shop, a museum, a phone service. It stays a real field: the keyboard, pasting and the code offered by the phone all work, and the dial dials them by itself.
On a 390-pixel phone the dial is as wide as the screen less the margins (358 pixels), the holes stay as big as a fingertip and are turned with the finger; on the dial a finger does not scroll the page (touch-action none), elsewhere it does. Touching the dial does not open the keyboard, which would cover the dial; the hidden field has a 16-pixel typeface, so with an external keyboard or a screen reader the page does not zoom in. Where it exists, the knock at the stop buzzes the phone.
The dial still turns with a finger, but does not run back: let go at the stop it fades for a moment and is already home, the ticks fill all together and the digit fades in. Typed digits and the SMS code do not turn the dial: the hole lights up and the digit appears in its box. No bounces, no entrance, and during the check the arc does not turn.
GSAP 3.15.0, Archivo (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 15 KB; the libraries: GSAP 28 KB.
Tested on 7 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.