
The dinosaur-bitten logo
Intro, SVG, Text
NewFree
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.
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>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
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 siteThe 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.
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.
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 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.
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.
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.
| Name | File | Default | What it changes |
|---|---|---|---|
NAME | script.js | 'Moonvale' | The logo as a word: every letter is a piece the saucer can take away. |
IMAGE | script.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. |
TAKEN | script.js | 2 | How 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. |
FLIPPED | script.js | 4 | The letter sent back upside down, counting from 0 without the spaces (in Moonvale number 4 is the v, which reads well upside down). |
UFO | script.js | 2.6 | How wide the flying saucer is, in letter heights. On a tall screen it gets a little bigger. |
FLIGHT | script.js | 1 | The speed of the saucer’s flights (the descent, the moves, the lap of honour, the getaway, the far pass): 2 is twice as fast. |
SPEED | script.js | 1 | The speed of the whole story: 2 is twice as fast, 0.5 half as fast. |
REST | script.js | 4 | How many seconds the logo stays with its holes before the letters come back. From 2.5 seconds up the saucer passes by far away. |
LOOP | script.js | true | Whether the letters come back and the story starts again. With false the logo keeps its holes and the upside-down letter keeps rocking. |
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.
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.
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.
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.
Tested on 10 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.