Skip to content
animorio
IT
Back to the library

The threads that draw the curve

SVG, ScrollGSAPMediumCompressed weight: Demo 6.6 KBGSAP + ScrollTrigger 45 KBLenis 5.3 KBFreeDownload the zip

Scroll inside the preview

A scroll animation in the minimal style: four thin arms with pins and, as you scroll down, straight threads stretched from pin to pin, one after the other, until their crossings draw a curved star that no thread draws on its own. Each thread twangs as it comes taut, the title Taut narrows and gains weight with every thread pulled, and at the end the curve is traced in vermilion. With the mouse you can pluck the threads.

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>The threads that draw the curve</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>
  <!-- a made-up embroidery thread maker, Tension. The stage sticks while you scroll: four thin arms with pins, and
       straight threads stretched pin to pin, one after the other, until their crossings draw a curved star that no
       thread draws on its own. The title gets heavier with every thread pulled taut. The threads are drawn by the script -->
  <main>
    <section class="corsa" data-corsa>
      <div class="palco" data-palco>
        <svg class="tela" data-tela aria-hidden="true">
          <g class="bracci" data-bracci></g>
          <g class="fili" data-fili></g>
          <path class="curva" data-curva d="" pathLength="1" />
        </svg>

        <header class="testa" data-entra>
          <span class="testa__nome">Tension</span>
          <span class="testa__nota">Embroidery thread, dyed by hand</span>
        </header>

        <div class="titolo-box" data-titolo-box>
          <h1 class="titolo" data-titolo>Taut</h1>
          <p class="sotto" data-sotto>Thread that holds its line. Every curve here is made of straight ones.</p>
        </div>

        <p class="cenno" data-entra><span class="cenno__dentro" data-cenno><span>Scroll</span><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M10 3v13M4.5 10.5 10 16l5.5-5.5"/></svg></span></p>
      </div>
    </section>
  </main>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/ScrollTrigger.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/lenis@1.3.26/dist/lenis.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.

16 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 “The threads that draw the curve” from Animorio and fit it into my site

What it does

The page of a made-up embroidery thread maker, Tension: ivory paper, the name at the top left and, on the right, Embroidery thread, dyed by hand; at the bottom left a huge title, Taut, very thin and wide. As it arrives, four thin arms grow out of a point on the right, up, right, down and left, and along each one the pin ticks appear, from the centre to the tip. As you scroll the stage stays still and the threads start to be stretched: the first goes from the pin near the centre on one arm to the pin at the tip of the next, the second from the next pin to the one before, and so on, a quarter at a time. Each thread is laid down a little slack, with a small belly, and when it reaches the end it pulls taut at once and twangs like a plucked string, less and less, until it stops. They are all straight, but their crossings draw a curve: after the four quarters there is a four-pointed star with curved sides. Meanwhile the title Taut gains weight and narrows on the width axis with every thread pulled, with a small bounce, until it is solid black and tight. Last, a vermilion line traces the curve that no thread draws on its own, and under the title the brand’s line appears. With the mouse, crossing the taut threads, every thread touched twangs, harder if the mouse is fast. Scrolling back up, the threads come off backwards and the title slackens.

How it works

Straight threads, a real curve

Thread i of a quarter goes from the pin at i/N on one arm to the pin at (N−i)/N on the next. The envelope of these lines is a parabola: the quadratic Bezier curve from one tip to the next with its handle at the centre. The final vermilion line is exactly that, four Q commands in one path.

The scroll lays, time twangs

A timeline with ScrollTrigger and scrub, on a sticky stage 100lvh tall with Lenis for smooth scrolling, tweens a single number: how much of the stringing is done. Each thread takes its own share of it (staggered, with power2.inOut). The twang runs on time instead: when a thread reaches 1 a damped sine starts, amplitude·e^(−t/RING)·sin(2π·7t), moving the control point of a Q curve along the thread’s normal. So a thread keeps ringing even when the scroll stops.

The taut title

On every change GSAP takes the font-variation-settings of Taut (variable Archivo) towards wght 120 + 660·u and wdth 125 − 55·u, where u is the share of threads pulled taut, with back.out(2): every thread gives it a small tug.

Plucking with the mouse

On every pointermove the script checks whether the segment from the previous position to the current one crosses a taut thread (two cross products of opposite sign, for both lines). The thread touched starts twanging again with an amplitude that grows with the mouse’s speed. A tap or a click plucks the threads that pass within 14 pixels of the finger.

Reduced motion

Nothing is laid and nothing twangs: the scroll goes through three stops (the arms, all the threads with the tight title, the vermilion curve with the line) and between one stop and the next the drawing changes with a fade.

Values to change

NameFileDefaultWhat it changes
PINSscript.js16The pins on each arm: more pins, more threads and a smoother curve.
ARMSscript.js4How many arms grow out of the centre (3 to 8): the star has as many points as arms.
SIZEscript.js0.38How long the arms are, as a share of the stage height.
TWANGscript.js1How hard each thread twangs as it comes taut (0 = it does not).
RINGscript.js0.7The seconds a twang takes to die away.
PULLscript.js1How much the title tightens: 0 = it does not change.
RIDEscript.js1How much scroll the whole thing takes: 2 is twice as long.

Try them in the Playground

When to use it

On the home page of a haberdashery, a yarn maker or an embroidery workshop; on the «how we work» page of a design or architecture studio; anywhere that wants the idea of many simple, straight things that together make a curved shape.

On phones

The same animation with the sizes adapted: the star sits at the top in the middle, nearly as wide as the screen, and the title underneath is larger; the threads twang just the same. Without a mouse a tap plucks the threads under the finger.

With reduced motion

Nothing is laid and nothing twangs: three stops on the scroll, the arms, all the threads with the title already tight and the vermilion curve with the line, which change with a fade.

Pitfalls

  • Joining pin i to pin N+1−i (the sum that feels natural) would put the envelope beyond the tips of the arms: the two distances must add up to exactly one arm, so i and N−i, and the first and last threads, which would lie on the arms, are left out.
  • The twang cannot live in the scrubbed timeline: it would stop with the scroll and play backwards when scrolling up. It is a damped sine in GSAP’s ticker, switched on when the thread reaches the end.
  • The title was the same word as the name at the top, Tension, and read twice: the title became Taut, which is also what happens to the threads.

Libraries

GSAP 3.15.0, ScrollTrigger (GSAP) 3.15.0, Lenis 1.3.26, Archivo (font variabile) 5.3.0.

Compressed with gzip, the three demo files weigh 6.6 KB; the libraries: GSAP + ScrollTrigger 45 KB, Lenis 5.3 KB.

Testing

Tested on 19 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