Skip to content
animorio
IT
Back to the library

The UFO-abducted logo

Intro, SVG, TextGSAPAdvancedCompressed weight: Demo 24 KBGSAP 28 KBFreeDownload the zip

A logo preview in three acts: the letters light up like a neon sign, then a flying saucer with an alien in its dome comes down, reads the logo with a scanner and takes letters away with its tractor beam: one clings on and stretches like rubber, another comes back upside down. In the Playground you type your own name or upload your own logo.

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 UFO-abducted logo</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/sora@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="scena">
    <!-- the stage: the script measures it, writes the logo in it and flies the saucer -->
    <svg class="palco" data-stage role="img" aria-label="Moonvale" xmlns="http://www.w3.org/2000/svg">
      <defs>
        <!-- the evening comes from the top of the sky -->
        <linearGradient id="dusk-fill" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" class="sera" stop-opacity="0.5" />
          <stop offset="1" class="sera" stop-opacity="0.08" />
        </linearGradient>
        <!-- the tractor beam: faint by the saucer, stronger where it lands -->
        <linearGradient id="beam-fill" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0" class="raggio-stop" stop-opacity="0.2" />
          <stop offset="1" class="raggio-stop" stop-opacity="0.5" />
        </linearGradient>
        <linearGradient id="trail-fill" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" data-trail-fill>
          <stop offset="0" class="raggio-stop" stop-opacity="0" />
          <stop offset="1" class="raggio-stop" stop-opacity="0.7" />
        </linearGradient>
        <!-- the metal of the saucer: a soft shine across the disc, darker towards the edges and underneath -->
        <linearGradient id="metal-fill" x1="0" y1="0" x2="1" y2="0">
          <stop offset="0" class="metallo-scuro" />
          <stop offset="0.22" class="metallo" />
          <stop offset="0.4" class="metallo-chiaro" />
          <stop offset="0.66" class="metallo" />
          <stop offset="1" class="metallo-scuro" />
        </linearGradient>
        <linearGradient id="band-fill" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0.68" class="metallo" />
          <stop offset="1" class="metallo-fondo" />
        </linearGradient>
        <linearGradient id="bowl-fill" x1="0" y1="0" x2="1" y2="0">
          <stop offset="0" class="metallo-fondo" />
          <stop offset="0.42" class="metallo-scuro" />
          <stop offset="0.55" class="metallo" />
          <stop offset="1" class="metallo-fondo" />
        </linearGradient>
        <!-- the soft shadow on the floor -->
        <radialGradient id="shadow-fill">
          <stop offset="0" class="ombra-stop" stop-opacity="1" />
          <stop offset="0.55" class="ombra-stop" stop-opacity="0.6" />
          <stop offset="1" class="ombra-stop" stop-opacity="0" />
        </radialGradient>
        <!-- the cabin is lit from the console -->
        <radialGradient id="cabin-fill" cx="0.5" cy="0.9" r="0.75">
          <stop offset="0" class="cabina-luce" />
          <stop offset="1" class="cabina" />
        </radialGradient>
        <linearGradient id="cabin-beam" x1="0" y1="1" x2="0" y2="0">
          <stop offset="0" class="cabina-luce" stop-opacity="0.55" />
          <stop offset="1" class="cabina-luce" stop-opacity="0" />
        </linearGradient>
        <radialGradient id="iris-fill" cx="0.5" cy="0.7" r="0.6">
          <stop offset="0" class="iride-chiara" />
          <stop offset="1" class="iride-scura" />
        </radialGradient>
        <!-- the outlines that keep the details inside their piece -->
        <clipPath id="ufo-bowl-clip"><path d="M-104 16C-98 46 -60 64 0 64C60 64 98 46 104 16Z" /></clipPath>
        <clipPath id="ufo-disc-clip"><ellipse cx="0" cy="0" rx="148.5" ry="28.5" /></clipPath>
        <clipPath id="ufo-dome-clip"><path d="M-78.5 -12C-78.5 -77 -43 -116.5 0 -116.5C43 -116.5 78.5 -77 78.5 -12Z" /></clipPath>
        <clipPath id="alien-suit-clip"><path d="M-26 0C-28 -24 -16 -38 0 -38C16 -38 28 -24 26 0Z" /></clipPath>
        <clipPath id="alien-head-clip"><path d="M-34 -62C-34 -80 -18 -88 0 -88C18 -88 34 -80 34 -62C34 -46 20 -37 0 -37C-20 -37 -34 -46 -34 -62Z" /></clipPath>
        <clipPath id="alien-eyes-clip"><ellipse cx="-13" cy="-63" rx="10.5" ry="12.5" /><ellipse cx="13" cy="-63" rx="10.5" ry="12.5" /></clipPath>
        <clipPath id="alien-grin-clip"><path d="M-9 -48.5Q0 -46.5 9 -48.5Q8 -38.6 0 -38.4Q-8 -38.6 -9 -48.5Z" /></clipPath>
        <clipPath id="alien-screen-clip"><rect x="-13" y="-18" width="26" height="9" rx="2" /></clipPath>
      </defs>

      <g data-world>
        <rect class="cielo-sera" fill="url(#dusk-fill)" data-dusk />
        <ellipse class="ombra" data-shadow />
        <g data-sockets></g>
        <g data-logo></g>
        <g data-trail></g>
        <!-- the beam, the scanner and the rings: drawn by the script every frame, from the hatch to the logo -->
        <g data-beam>
          <ellipse class="pozza-luce" data-pool />
          <polygon class="raggio" fill="url(#beam-fill)" data-cone />
          <g data-rings></g>
          <g data-motes></g>
        </g>
        <g data-scan>
          <polygon class="scansione-fascio" data-scan-cone />
          <line class="scansione-riga" data-scan-line />
        </g>

        <!-- the saucer: drawn round its centre, the middle of the disc is 0 0 -->
        <g data-ufo-place>
          <g data-ufo>
            <!-- the heat under the engine: wavy strokes that drift down while it hovers -->
            <g data-heat></g>
            <!-- the bowl underneath: brushed metal, panels with rivets, two portholes -->
            <path class="ufo-conca" d="M-104 16C-98 46 -60 64 0 64C60 64 98 46 104 16Z" />
            <g clip-path="url(#ufo-bowl-clip)">
              <path class="ufo-ombra-fascia" d="M-110 20Q0 64 110 20" />
              <path class="ufo-righe" d="M-80 30Q-74 46 -60 56M80 30Q74 46 60 56M-40 40Q-36 52 -30 62M40 40Q36 52 30 62" />
              <path class="rivetti" d="M-74 40.5h0.01M-68 48.5h0.01M-37.6 47h0.01M-34.4 55h0.01M74 40.5h0.01M68 48.5h0.01M37.6 47h0.01M34.4 55h0.01" />
              <g class="oblo">
                <ellipse class="oblo-cornice" cx="-58" cy="46" rx="8.5" ry="5.6" />
                <ellipse class="oblo-vetro" cx="-58" cy="46" rx="5.6" ry="3.4" />
                <path class="oblo-lucido" d="M-61 45Q-59.5 43.4 -57 43.3" />
                <ellipse class="oblo-cornice" cx="58" cy="46" rx="8.5" ry="5.6" />
                <ellipse class="oblo-vetro" cx="58" cy="46" rx="5.6" ry="3.4" />
                <path class="oblo-lucido" d="M55 45Q56.5 43.4 59 43.3" />
              </g>
            </g>
            <!-- the engine ring the beam comes out of, with its fins, and the hatch -->
            <path class="aletta" d="M-27 66L-33 76L-22 74L-19 68ZM27 66L33 76L22 74L19 68ZM-33 62L-44 69L-36 71L-30 66ZM33 62L44 69L36 71L30 66Z" />
            <ellipse class="motore" cx="0" cy="62" rx="34" ry="9" />
            <path class="ufo-righe" d="M-26 66.5Q0 72.5 26 66.5" />
            <g data-hatch>
              <ellipse class="botola" cx="0" cy="62" rx="22" ry="5.6" />
              <path class="botola-iride" d="M-6 62L-17 59M6 62L17 59M-6 62L-15 66M6 62L15 66M0 62L0 57" />
              <ellipse class="botola-luce" cx="0" cy="62" rx="16" ry="3.4" data-hatch-glow />
            </g>
            <!-- the rim, then the disc on top of it: the rim shows as a band, where the lights run -->
            <ellipse class="ufo-fascia" cx="0" cy="12" rx="150" ry="30" />
            <g data-lights></g>
            <ellipse class="ufo" cx="0" cy="0" rx="150" ry="30" />
            <!-- the plates of the disc, their seams and rivets, and the signs of a long service -->
            <g clip-path="url(#ufo-disc-clip)">
              <g data-seams></g>
              <path class="graffio" d="M-70 15L-52 20.5M-66 19.5L-56 22.5M40 22L58 19M100 8L112 4.5" />
              <g transform="rotate(-8 -112 10)">
                <rect class="toppa" x="-124" y="4" width="22" height="12" rx="2" />
                <path class="rivetti rivetti--fini" d="M-120.5 7h0.01M-105.5 7h0.01M-120.5 13h0.01M-105.5 13h0.01" />
              </g>
              <path class="ammaccatura" d="M78 13C82 9 92 9 95 14C91 12.5 84 12.5 78 13Z" />
              <path class="ammaccatura-luce" d="M79 15.4C84 17.6 91 17.4 95 15.6" />
            </g>
            <ellipse class="ufo-chiaro" cx="0" cy="-6" rx="112" ry="19" />
            <ellipse class="ufo-solco" cx="0" cy="-7" rx="97" ry="15" />
            <path class="ufo-lucido" d="M-130 -10C-104 -22 -64 -27 -24 -29" />

            <!-- the dish that turns, on the left of the deck, and the whip aerial with its pennant on the right -->
            <rect class="ufo-scuro" x="-109" y="-27" width="6" height="20" rx="2" />
            <ellipse class="ufo-scuro" cx="-106" cy="-7.5" rx="8" ry="3" />
            <g data-dish>
              <g transform="rotate(-20 -106 -32)">
                <path class="parabola-dietro" d="M-121 -32Q-106 -15 -91 -32Z" />
                <ellipse class="parabola" cx="-106" cy="-32" rx="15" ry="5.4" />
                <path class="parabola-braccio" d="M-112 -31L-106 -45L-100 -31" />
                <rect class="parabola-testa" x="-108.5" y="-49" width="5" height="5" rx="1.4" />
              </g>
            </g>
            <ellipse class="ufo-scuro" cx="104" cy="-7" rx="6.5" ry="2.6" />
            <g data-whip>
              <path class="antennina" d="M104 -8L106 -40" />
              <path class="bandierina" d="M106 -40L119 -37L106 -32Z" data-pennant />
            </g>

            <!-- the glass dome: its back with the light of the cabin, the floor, the controls, the pilot, the console -->
            <path class="cupola-dietro" d="M-80 -12C-80 -78 -44 -118 0 -118C44 -118 80 -78 80 -12Z" />
            <ellipse class="ufo-scuro" cx="0" cy="-12" rx="80" ry="10" />
            <path class="luce-cabina" d="M-14 -16L14 -16L30 -70L-30 -70Z" />
            <g data-stick>
              <rect class="leva" x="-45.5" y="-37" width="3" height="27" rx="1.4" />
              <rect class="leva-pomo leva-pomo--cloche" x="-47" y="-42" width="6" height="7" rx="2.6" />
            </g>
            <g data-lever>
              <rect class="leva" x="42.5" y="-36" width="3" height="26" rx="1.4" />
              <ellipse class="leva-pomo" cx="44" cy="-37" rx="4.6" ry="3.6" />
            </g>

            <!-- the pilot -->
            <g data-alien>
              <g data-alien-body>
                <path class="tuta" d="M-26 0C-28 -24 -16 -38 0 -38C16 -38 28 -24 26 0Z" />
                <g clip-path="url(#alien-suit-clip)">
                  <path class="cinghia-bordo" d="M-19 -36L4 -12M19 -36L-4 -12" />
                  <path class="cinghia" d="M-19 -36L4 -12M19 -36L-4 -12" />
                  <path class="tuta-righe" d="M-24 -18Q0 -13 24 -18" />
                </g>
                <path class="stemma" d="M-4.5 -31L4.5 -31L4.5 -27Q4.5 -23.6 0 -22.2Q-4.5 -23.6 -4.5 -27Z" />
                <path class="stemma-segno" d="M-2.6 -26.4A2.6 2.6 0 1 0 2.6 -26.4A2.6 2.6 0 1 0 -2.6 -26.4M-4 -25.2L4 -27.6" />
                <path class="colletto" d="M-17 -35Q0 -27 17 -35Q16 -42 0 -42Q-16 -42 -17 -35Z" />
              </g>
              <g data-alien-head>
                <g data-antenna-l>
                  <path class="antenna" d="M-9 -84L-14 -94" />
                  <g data-antenna-l2>
                    <path class="antenna" d="M-14 -94L-22.5 -101.5" />
                    <circle class="antenna-punta" cx="-24" cy="-104" r="4.8" />
                    <path class="antenna-lucido" d="M-26.4 -105.4Q-25.6 -107.2 -23.6 -107.4" />
                  </g>
                  <circle class="antenna-giunto" cx="-14" cy="-94" r="2.2" />
                </g>
                <g data-antenna-r>
                  <path class="antenna" d="M9 -84L14 -94" />
                  <g data-antenna-r2>
                    <path class="antenna" d="M14 -94L22.5 -101.5" />
                    <circle class="antenna-punta" cx="24" cy="-104" r="4.8" />
                    <path class="antenna-lucido" d="M21.6 -105.4Q22.4 -107.2 24.4 -107.4" />
                  </g>
                  <circle class="antenna-giunto" cx="14" cy="-94" r="2.2" />
                </g>
                <path class="alieno" d="M-34 -62C-34 -80 -18 -88 0 -88C18 -88 34 -80 34 -62C34 -46 20 -37 0 -37C-20 -37 -34 -46 -34 -62Z" />
                <g clip-path="url(#alien-head-clip)">
                  <ellipse class="alieno-mento" cx="0" cy="-35" rx="36" ry="9" />
                  <path class="alieno-macchia" d="M17 -80a3.4 2.5 -15 1 0 6.8 0a3.4 2.5 -15 1 0 -6.8 0ZM25 -72a2.1 1.7 0 1 0 4.2 0a2.1 1.7 0 1 0 -4.2 0ZM-29 -72a2.7 2.1 20 1 0 5.4 0a2.7 2.1 20 1 0 -5.4 0ZM-22 -81a1.8 1.4 0 1 0 3.6 0a1.8 1.4 0 1 0 -3.6 0ZM27 -60a2.3 1.8 0 1 0 4.6 0a2.3 1.8 0 1 0 -4.6 0ZM-32 -58a1.7 1.4 0 1 0 3.4 0a1.7 1.4 0 1 0 -3.4 0ZM4 -85a1.6 1.2 0 1 0 3.2 0a1.6 1.2 0 1 0 -3.2 0ZM-8 -86.4a1.3 1 0 1 0 2.6 0a1.3 1 0 1 0 -2.6 0ZM29.6 -67a1.2 1 0 1 0 2.4 0a1.2 1 0 1 0 -2.4 0ZM-30.6 -65a1.2 1 0 1 0 2.4 0a1.2 1 0 1 0 -2.4 0Z" />
                </g>
                <path class="alieno-lucido" d="M-24 -78C-18 -84 -10 -86 -2 -86" />
                <g data-cheeks>
                  <ellipse class="guancia" cx="-24" cy="-49" rx="5.5" ry="3.2" />
                  <ellipse class="guancia" cx="24" cy="-49" rx="5.5" ry="3.2" />
                </g>
                <ellipse class="occhio" cx="-13" cy="-63" rx="10.5" ry="12.5" />
                <ellipse class="occhio" cx="13" cy="-63" rx="10.5" ry="12.5" />
                <g clip-path="url(#alien-eyes-clip)">
                  <g data-pupils>
                    <circle class="iride" cx="-12" cy="-61" r="6.8" />
                    <circle class="pupilla" cx="-12" cy="-61" r="3.6" />
                    <circle class="riflesso" cx="-14.6" cy="-64.4" r="2.2" />
                    <circle class="riflesso" cx="-9.2" cy="-58.4" r="1.1" />
                    <circle class="iride" cx="14" cy="-61" r="6.8" />
                    <circle class="pupilla" cx="14" cy="-61" r="3.6" />
                    <circle class="riflesso" cx="11.4" cy="-64.4" r="2.2" />
                    <circle class="riflesso" cx="16.8" cy="-58.4" r="1.1" />
                  </g>
                </g>
                <g data-lids>
                  <ellipse class="palpebra" cx="-13" cy="-63" rx="11.6" ry="13.6" />
                  <ellipse class="palpebra" cx="13" cy="-63" rx="11.6" ry="13.6" />
                </g>
                <g data-brow-l><path class="sopracciglio" d="M-21.5 -79.5Q-14 -84.5 -6 -81.5" /></g>
                <g data-brow-r><path class="sopracciglio" d="M21.5 -79.5Q14 -84.5 6 -81.5" /></g>
                <!-- the mouths: one shows at a time, by the mood of the moment -->
                <path class="bocca-linea" d="M-7 -47Q0 -41 7 -47" data-mouth />
                <g data-mouth-grin>
                  <path class="bocca-aperta" d="M-9 -48.5Q0 -46.5 9 -48.5Q8 -38.6 0 -38.4Q-8 -38.6 -9 -48.5Z" />
                  <g clip-path="url(#alien-grin-clip)">
                    <ellipse class="lingua" cx="0" cy="-38.6" rx="6" ry="3.6" />
                    <rect class="dentino" x="1.6" y="-49.5" width="4.2" height="4" rx="1" />
                  </g>
                  <path class="bocca-bordo" d="M-9 -48.5Q0 -46.5 9 -48.5Q8 -38.6 0 -38.4Q-8 -38.6 -9 -48.5Z" />
                </g>
                <g data-mouth-tongue>
                  <path class="lingua" d="M2.4 -46.4Q7.6 -46.8 8.6 -42.6Q8.2 -40 5.6 -40.6Q3.4 -41.4 2.4 -44Z" />
                  <path class="bocca-linea" d="M-6.5 -45Q-1 -43.6 6 -46.6" />
                </g>
                <g data-mouth-yuck>
                  <path class="lingua" d="M-3.4 -46Q-4 -38.4 0 -38.2Q4 -38.4 3.4 -46Z" />
                  <path class="lingua-riga" d="M0 -45L0 -41" />
                  <path class="bocca-linea" d="M-9 -46Q-6.5 -49.5 -3.5 -46.4Q0 -44 3.5 -46.4Q6.5 -49.5 9 -46" />
                </g>
                <g data-mouth-grit>
                  <path class="denti" d="M-9.5 -49.5L9.5 -49.5Q10.4 -43 7 -42L-7 -42Q-10.4 -43 -9.5 -49.5Z" />
                  <path class="denti-righe" d="M-9.6 -45.6L9.6 -45.6M-4.6 -49.5L-4.6 -42M0 -49.5L0 -42M4.6 -49.5L4.6 -42" />
                </g>
                <ellipse class="bocca-o" cx="0" cy="-45" rx="4.2" ry="5.2" data-mouth-o />
                <!-- the sweat of the tug of war -->
                <path class="goccia" d="M31 -84Q35 -78.4 33.2 -75.6Q31 -73 28.8 -75.6Q27 -78.4 31 -84Z" data-sweat-a />
                <path class="goccia" d="M-33 -76Q-29 -70.4 -30.8 -67.6Q-33 -65 -35.2 -67.6Q-37 -70.4 -33 -76Z" data-sweat-b />
              </g>
              <!-- the arms, two strokes each (a dark wide one for the outline), a cuff, and the three-fingered hands -->
              <g data-arm-l>
                <path class="braccio-bordo" d="M-20 -31Q-32 -38 -41 -33" />
                <path class="braccio" d="M-20 -31Q-32 -38 -41 -33" />
                <path class="polsino-bordo" d="M-37.6 -37.2L-40.4 -30.6" />
                <path class="polsino" d="M-37.6 -37.2L-40.4 -30.6" />
                <path class="mano" d="M-49 -33C-50 -38.4 -44 -39.4 -42 -36.6C-40 -38.8 -36 -37.6 -37.4 -34C-35 -32 -36 -27 -40 -27C-45 -26 -49 -28 -49 -33Z" />
                <path class="mano-dita" d="M-44.6 -35.4L-44.8 -30.2M-41 -35.2L-41.2 -29.8" />
              </g>
              <g data-arm-r>
                <path class="braccio-bordo" d="M20 -31Q32 -38 41 -33" />
                <path class="braccio" d="M20 -31Q32 -38 41 -33" />
                <path class="polsino-bordo" d="M37.6 -37.2L40.4 -30.6" />
                <path class="polsino" d="M37.6 -37.2L40.4 -30.6" />
                <path class="mano" d="M49 -33C50 -38.4 44 -39.4 42 -36.6C40 -38.8 36 -37.6 37.4 -34C35 -32 36 -27 40 -27C45 -26 49 -28 49 -33Z" />
                <path class="mano-dita" d="M44.6 -35.4L44.8 -30.2M41 -35.2L41.2 -29.8" />
              </g>
            </g>

            <!-- the console, in front of the pilot: a little screen, buttons, and the big one it presses -->
            <path class="cruscotto" d="M-62 -8L-56 -20Q0 -27 56 -20L62 -8Q0 -3 -62 -8Z" />
            <path class="cruscotto-piano" d="M-56 -20Q0 -27 56 -20L58 -16.5Q0 -23.5 -58 -16.5Z" />
            <rect class="schermo" x="-13" y="-18" width="26" height="9" rx="2" />
            <g clip-path="url(#alien-screen-clip)">
              <path class="schermo-griglia" d="M-13 -13.5L13 -13.5M-6.5 -18L-6.5 -9M0 -18L0 -9M6.5 -18L6.5 -9" />
              <path class="onda" data-wave />
            </g>
            <rect class="tasto tasto--a" x="-34" y="-15" width="6" height="3.4" rx="1.2" />
            <rect class="tasto tasto--b" x="-25" y="-15" width="6" height="3.4" rx="1.2" />
            <rect class="tasto tasto--c" x="19" y="-15" width="6" height="3.4" rx="1.2" />
            <g data-button>
              <rect class="tasto tasto--grande" x="35.6" y="-21.6" width="7.4" height="3.2" rx="1.4" />
              <rect class="tasto-premuto" x="36.8" y="-21" width="5" height="2" rx="0.9" data-button-lit />
            </g>

            <path class="cupola" d="M-80 -12C-80 -78 -44 -118 0 -118C44 -118 80 -78 80 -12Z" />
            <g clip-path="url(#ufo-dome-clip)">
              <path class="cupola-scia" d="M-18 -128L2 -128L-30 0L-50 0Z" data-glint />
            </g>
            <path class="cupola-lucido" d="M-62 -36C-64 -72 -44 -100 -18 -109" />
            <path class="cupola-lucido cupola-lucido--fine" d="M50 -92C58 -82 63 -68 64 -56" />
            <path class="cupola-lucido cupola-lucido--punto" d="M-54 -26C-55 -29 -55 -31 -54.6 -33" />
            <!-- the collar of the dome: a rubber gasket over a ring of bolts -->
            <path class="ufo-chiaro" d="M-86 -12A86 10 0 0 0 86 -12L86 -6A86 10 0 0 1 -86 -6Z" />
            <path class="guarnizione" d="M-81 -11.6A81 9.4 0 0 0 81 -11.6" />
            <path class="rivetti" d="M-70 -1.4h0.01M-42 1.6h0.01M-14 3h0.01M14 3h0.01M42 1.6h0.01M70 -1.4h0.01" />
          </g>
        </g>

        <g data-fx></g>
      </g>
    </svg>
    <p class="nota">Click or tap to see it again</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.

44 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 UFO-abducted logo” from Animorio and fit it into my site

What it does

On a pale sky there is the unlit sign of a made-up brand, Moonvale, drawn in dashes: the letters light up one after the other with the flicker of a neon tube, a few sparks and a bounce. The sky darkens a little and a flying saucer comes swaying down from above, its rim lights running round and, under a glass dome, a green alien with big eyes, eyelids, buzzing antennae and little hands on the dashboard; as it gets near, the sign stutters. It stops over the logo, the alien looks it all over, then a thin scanner reads it from left to right and every letter lights up as it passes. The tractor beam opens, a cone of light with rings climbing up: one letter comes loose, trembles, turns slowly and rises to the hatch, which swallows it (the alien blushes, pleased). Another rises half way, the alien leans in to look, shakes its head and the beam sends it back down upside down. The last one clings on: the beam pulls, the letter stretches like rubber, the saucer strains, until the letter lets go and shoots up like a catapult. The saucer does a lap of honour with confetti and makes off up the diagonal with the letter hanging underneath, leaving a trail. The logo stays with its dashed holes and the upside-down letter rocking, while the saucer passes by small and far away; then the letters come back (the stolen one floats down on a parachute, the upside-down one flips over) and the story starts again. A click restarts it. A picture can take the place of the word, cut in strips: the beam takes the strips.

How it works

A stage to size

The stage is an SVG whose viewBox is as big as the window, so one unit is one pixel. The letters are measured on a canvas in the same typeface: measureText gives the advance and, with actualBoundingBox, the true ink of every letter (left, right, top, bottom), and that gives a single size for the saucer, the beam and the logo. A tall screen has sky to spare: the saucer grows up to half the screen wide and the beam gets longer.

Letters in layers

Every letter is an outer group that moves, turns and scales around the centre of its ink (svgOrigin, not getBBox, which for text gives the em box) and an inner group that stretches from its foot: so the clinging letter stays on the line while it is pulled upwards. Under the logo there is a dashed copy of every letter: it is the unlit sign at the start and the hole when the letter is gone.

The saucer and its pilot

Saucer, dome and alien are drawn once in the page, in pieces and with an outline: the metal bowl with panels, rivets and two portholes, the engine ring with its fins and the iris hatch, the rim with twelve bar lights, the disc with a metal shine, plate seams, scratches, a riveted patch and a dent, the dish that turns and the whip aerial with its pennant. Under the dome (gleams, gasket, cabin light) sit the console with a little screen, buttons, a stick and a lever, and the alien with suit, collar, straps and badge, spotted skin, eyes with a shaded iris and two gleams, eyelids, eyebrows and five mouths, one per mood. The details stay inside their shape with a clipPath; every piece turns on its joint (the antennae have two, so the tip comes late). The ticker, from the timeline's time, turns the dish, pitches the disc, slides the gleam over the dome and the wave over the screen, and lifts the heat under the engine: a frame at a given instant is always the same.

The tractor beam

The cone is a polygon redrawn every frame from the hatch, wherever the saucer is and however it tilts, to the letter: if the letter is at the end of the word the saucer stays on screen and the beam leans over. The rings are ellipses that climb and narrow with the cone (or fall, when the beam sends the letter back), the specks spin as they rise; the scanner is a thin blade with a line that sweeps.

The letter carried off

When the letter lets go, the timeline takes a single number from 0 to 1 with the overshoot of back.out, and the ticker puts the letter between the line and the point under the hatch, worked out each time from where the saucer is: during the lap of honour, the getaway and the far pass the letter always hangs straight down and swings, and shrinks with the saucer. The trail of the getaway is a triangle from the tail to the saucer, with a gradient in screen coordinates.

Direction and your logo

The whole story is one timeline, with timeScale for the speed and labels for every moment (arrive, scan, take, inspect, flip, grip, snap, party, escape, rest, heal). The letters coming back use fromTo with immediateRender false; at the end the scene is rebuilt from «arrive». If IMAGE holds an address, the logo becomes that picture cut in strips: it stays whole, the strips that leave are copies cut by a clipPath, and a mask opens their hole only when they go. In the Playground, next to the field, there is a button to upload a file, which goes into the code as a data: address.

Values to change

NameFileDefaultWhat it changes
NAMEscript.js'Moonvale'The logo as a word: every letter is a piece the saucer can take away.
IMAGEscript.js''The logo as a picture: the address of a file, or upload it from your computer. If there is one, it takes the place of the word and the beam takes its strips.
TAKENscript.js2How many letters the saucer takes away: the first rises slowly, the others quicker, the last one clings on and leaves hanging under the saucer. With 0 there is only the upside-down one.
FLIPPEDscript.js4The letter sent back upside down, counting from 0 without the spaces (in Moonvale number 4 is the v, which reads well upside down).
UFOscript.js2.6How wide the flying saucer is, in letter heights. On a tall screen it gets a little bigger.
FLIGHTscript.js1The speed of the saucer’s flights (the descent, the moves, the lap of honour, the getaway, the far pass): 2 is twice as fast.
SPEEDscript.js1The speed of the whole story: 2 is twice as fast, 0.5 half as fast.
RESTscript.js4How many seconds the logo stays with its holes before the letters come back. From 2.5 seconds up the saucer passes by far away.
LOOPscript.jstrueWhether the letters come back and the story starts again. With false the logo keeps its holes and the upside-down letter keeps rocking.

Try them in the Playground

When to use it

To present a logo in a way nobody forgets: a preview for a client, the opening of a studio’s site or video, a 404 page («someone took the page») or a loading screen with a sense of humour, a social post. It works with a written wordmark and with a picture.

On phones

The same story, with the sizes adapted: on a tall screen the saucer is up to half the screen wide and the beam is longer; over the letters at the ends of the word the saucer stays on screen and the beam leans over. A tap restarts it.

With reduced motion

Nothing moves: the logo fades in, the sky darkens, the saucer appears still with its beam on, then the taken letters fade out, the upside-down one swaps with its turned copy and the saucer fades away. If the story starts again, the return is a fade too.

Pitfalls

  • getBBox of a text gives the em box, not the ink: turned half round that centre, a lowercase letter ended up floating above the line. The centre is worked out with actualBoundingBox letter by letter and passed as svgOrigin.
  • After half a turn the foot of the letter is on top: the squash on landing and the rocking of the upside-down letter turn around its top, which now touches the line.
  • The letter carried off is placed by the ticker, not by the timeline: seeking back before the snap left it in the sky. Now, before the snap label, it goes back home.
  • fromTo inside a timeline draws its start values straight away: the letters coming back from the sky vanished at the very start of the story. It needs immediateRender false.
  • On a phone, over the last letter, the saucer stuck half out of the screen: it stops before the edge and the beam, redrawn every frame from the hatch to the letter, leans over.
  • Strips of a picture cut and placed side by side leave thin lines where they meet: the picture stays whole and only the strips that leave are copies, with a mask that opens their hole when they go.
  • The upside-down a of Moonvale read as an e and the joke was lost: the default upside-down letter is the v, which becomes a Λ.
  • With longer arms holding the stick and the lever, the cheer at 95 degrees put the hands in front of the face: the arms now go up about fifty degrees, beside the head.
  • The dish turns by squeezing its width: for an instant it was zero wide and vanished, and being symmetric you could not tell which way it turned. It leans to one side and never goes below a tenth of its width.

Libraries

GSAP 3.15.0, Sora (font variabile) 5.3.0.

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

Testing

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