Skip to content
animorio
IT
Back to the library

Needles that write

Hover, TextCanvas, GSAPAdvancedCompressed weight: Demo 9.9 KBGSAP 28 KBFreeDownload the zip

A field of thin dashes, like compass needles, that all turn toward the pointer with a wave of delay and a small bounce. Where the pointer rests, the needles around it stretch into lines and write a word in negative; move it, and they let it go. In the minimal style.

The code

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>Needles that write</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/mona-sans@5.3.0/wdth.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage" data-stage>
    <!-- the field: a grid of thin needles drawn on a canvas by the script -->
    <canvas class="field" data-field aria-hidden="true"></canvas>

    <!-- the mark: a small needle that turns with the others, and the name -->
    <header class="mark" data-label>
      <svg class="mark__needle" data-mark viewBox="-12 -12 24 24" aria-hidden="true">
        <path class="mark__tail" d="M0 0 L-2.6 0 L0 10.5 L2.6 0 Z"/>
        <path class="mark__tip" d="M0 0 L-2.6 0 L0 -10.5 L2.6 0 Z"/>
      </svg>
      <span class="mark__name" data-rise>Lodestone</span>
    </header>

    <!-- the hint: what to do, and what to do next once a word is written -->
    <p class="hint" data-label>
      <span class="hint__roll" data-roll>
        <span class="hint__line" data-hint-idle>Rest the pointer anywhere.</span>
        <span class="hint__line" data-hint-word>Move, and the needles let go.</span>
      </span>
    </p>

    <!-- the word the needles are writing, for screen readers -->
    <p class="sr" data-said></p>
  </main>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
  <script src="script.js"></script>
</body>
</html>

Playground

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.

17 values to change

Or ask Claude Code for it

With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:

Take “Needles that write” from Animorio and fit it into my site

What it does

A paper-coloured page covered by a grid of thin dashes, all alike, with the made-up brand Lodestone in one corner (a small compass needle by its name) and a line saying what to do in the other. On opening the needles sprout from the centre out to the edges, each with a little elastic snap, already turned north. Then every needle turns toward the pointer, like a compass needle toward a magnet: the near ones at once, the far ones a little later, so every move runs across the field as a wave, and each one goes a hair past its mark before it stops. Near the pointer the needles grow longer and their tips turn red, like the north end of a compass. When the pointer stays still for a moment, the needles around it turn flat and stretch into close lines, while new ones sprout between the rows, from the pointer outward: the word is what the lines leave empty, written in negative inside a block of hatching. The letters sit on whole rows, so their tops and feet are clean, and every needle that touches a letter gets shorter and slides aside just enough to keep out of it. As soon as the pointer moves again, the needles let the word go and turn back to look at it; at the next stop they write the next word (North, Still, Here). The needle of the brand follows the pointer too, and the line at the bottom rolls to a new sentence while a word is written. With no pointer on the page, an invisible one tours the field by itself and stops three times.

How it works

The field on a canvas

The needles are the points of a grid, CELL pixels apart (fewer on the phone, so that the words have rows enough). For each of them the script keeps the angle, the length and a shift along its line in typed arrays, each with its own speed. On every frame it draws them all on a single canvas, grouped by thickness: one path for each thickness, first the ink and then the red tips. Where the two labels stand there are no needles.

The wave comes from memory

The script remembers where the pointer was over the last few seconds. Each needle does not look at the pointer as it is now but as it was a moment ago, the older the further the needle is (WAVE milliseconds for every pixel). Rather than searching that memory thousands of times, the delays are split into 48 steps: on every frame the place for each step is worked out once and each needle takes its own.

Every needle is a spring

The angle, the length and the shift follow their targets as damped springs, worked out in small steps of a hundred and twentieth of a second: that is what gives the light bounce. BOUNCE lowers the damping. The angle always takes the short way round (a whole turn is added or taken away), so a needle never spins all the way round to land a little further on.

The word in negative

When the pointer stops, the script picks the largest letters that fit, trying three widths of the variable typeface, and sets them on whole rows of needles. Inside the block the rows are doubled: between two rows of needles a third one comes out of nothing, already flat, only to build the letters, so the diagonals of the N and the curves of the O and R come out continuous. The word is drawn in black on a hidden canvas and, for every needle of the block, seventeen points along its line are checked: the longest stretch clear of the letters is what is left of the needle, which shortens and slides there. The needles wholly inside a letter disappear.

Writing in a wave, and touring alone

A single number, write, goes from 0 to 1 with GSAP; each needle feels it late according to its distance from the centre of the word, so the writing starts at the pointer and spreads out. Past a third the needle turns flat. Letting the word go, the same number goes back to 0. With no pointer, a repeating GSAP timeline moves an invisible pointer to three stops and calls the writing at each; the first real move stops it.

Values to change

NameFileDefaultWhat it changes
WORDSscript.js['NORTH', 'STILL', 'HERE']The words the needles write, one at each stop, in turn. Short and in capitals work best: the letters are made of rows of needles.
CELLscript.js18The space between two needles on a wide screen, in pixels. On the phone it gets smaller by itself.
WAVEscript.js0.6How late the far needles turn: milliseconds for every pixel of distance from the pointer (0 = all together).
BOUNCEscript.js0.5How far the needles swing past their mark before they settle (0 = not at all).
REACHscript.js6How far around the pointer the needles grow and take the red tip, in needles.
RESTscript.js0.3The seconds the pointer has to stay still before the word is written.
WRITE_TIMEscript.js1The seconds the writing takes to spread from the pointer to the edge of the block.
WEIGHTscript.js760The weight of the cut-out letters, from 200 to 900: lighter ones keep more hatching inside, heavier ones read louder.

Try them in the Playground

When to use it

At the top of a design site, an architecture studio or a brand that wants a quiet but living front page: the field reacts at once and rewards whoever stops with a word (the name, a motto, a date). It also works as the background of an about page, a coming-soon page or as a break between two sections.

On phones

The same animation with the sizes adapted: the needles are closer and a little finer, so the letters have rows enough, and the typeface narrows to fit the word in the width. The finger is the pointer: dragging, the needles follow it in a wave, lifting it the word is written where it stopped, and a new touch lets it go. After a few seconds without touches the tour starts again by itself.

With reduced motion

Nothing turns and nothing moves: the needles stand still pointing north and the first word is already written in the middle. Resting the pointer somewhere else (or tapping), the word fades out and comes back there, already written.

Pitfalls

  • With a single row of needles every 18 pixels the word looked like broken bars: the N in pieces, the O and R hard to tell apart. Doubled rows inside the block, taller letters, a full but not black weight, a little letter spacing and the width picked among three (the one giving the most rows) make them read at first glance, even on the phone.
  • A needle that shrinks to a few pixels, with round caps, becomes a dot: below a certain length it is not drawn at all, and a clear stretch shorter than a quarter of a needle is not kept.
  • The pointer that tours by itself must not be stopped with killTweensOf on the object it moves: that would kill the tweens inside the tour timeline too, which would never start again. The timeline is paused and only the homing tween is killed.
  • Letters placed at any height were cut in half by a row of needles, with a ragged top: the top and the foot of the capitals fall exactly between two rows (counting the ones in between too).
  • The angle must always take the short way round, adding or taking away a whole turn from the target: otherwise a needle going from 179 to -179 degrees spins all the way round.
  • The pointer autopilot of the previews never stops: to show the word in the video the demo tours by itself, driven by a GSAP timeline, and the card uses the loop autopilot.

Libraries

GSAP 3.15.0, Mona Sans (font variabile) 5.3.0.

Compressed with gzip, the three demo files weigh 9.9 KB; the libraries: GSAP 28 KB.

Testing

Tested on 14 October 2026

  • Desktop: Done
  • Phone: Done
  • Reduced motion: Done
  • Safari on iPhone: To do

License

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.

All animations