惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Cybersecurity and Infrastructure Security Agency CISA
D
Darknet – Hacking Tools, Hacker News & Cyber Security
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
S
Schneier on Security
L
Lohrmann on Cybersecurity
S
Securelist
P
Palo Alto Networks Blog
SecWiki News
SecWiki News
T
Troy Hunt's Blog
H
Hacker News: Front Page
AWS News Blog
AWS News Blog
Latest news
Latest news
Hacker News - Newest:
Hacker News - Newest: "LLM"
NISL@THU
NISL@THU
The Hacker News
The Hacker News
F
Full Disclosure
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
大猫的无限游戏
大猫的无限游戏
O
OpenAI News
P
Proofpoint News Feed
Know Your Adversary
Know Your Adversary
G
GRAHAM CLULEY
博客园_首页
Attack and Defense Labs
Attack and Defense Labs
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Security Latest
Security Latest
云风的 BLOG
云风的 BLOG
K
Kaspersky official blog
WordPress大学
WordPress大学
www.infosecurity-magazine.com
www.infosecurity-magazine.com
宝玉的分享
宝玉的分享
L
LINUX DO - 热门话题
博客园 - 叶小钗
L
LINUX DO - 最新话题
Martin Fowler
Martin Fowler
N
News | PayPal Newsroom
Project Zero
Project Zero
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
PCI Perspectives
PCI Perspectives
月光博客
月光博客
IT之家
IT之家
Recent Announcements
Recent Announcements
T
The Exploit Database - CXSecurity.com
D
DataBreaches.Net
J
Java Code Geeks
酷 壳 – CoolShell
酷 壳 – CoolShell
Last Week in AI
Last Week in AI
Google Online Security Blog
Google Online Security Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知

Codrops

Meet the Speakers of the First Three.js Conference | Codrops The Architecture Behind Trionn: Coordinating GSAP, Three.js, Lenis, and Web Audio | Codrops Where Stories Become Interactive Worlds: How makemepulse Brings Ideas to Life Across Web, XR, and Beyond | Codrops The Sleepers: Creating an Atmospheric WebGL Experience with Lightweight Techniques Building an Interactive Wave Propagation Cube Grid with Three.js | Codrops Ten Years Away: Designing an Interactive Comic for Studio375’s Tenth Anniversary | Codrops Building a Scroll-Driven 3D Gallery Using a Blender Camera Path with Three.js and GSAP | Codrops From Years of Client Work to a Next.js + Sanity Starter Kit | Codrops Sculpting a Digital Athlete: Capturing Stefanos Tsitsipas Beyond the Court | Codrops Building Persistent Page Transitions with WebGPU and Vanilla JavaScript | Codrops Inside Bisous: Designing an Editorial Experience for Cinematic CGI | Codrops Engineering the Web Experience Behind Shopify’s Spring ’26 Edition: Everywhere | Codrops Shaping Stories into Experience: The Work of Kevin Lam | Codrops Testing What Users Actually See with Vitest and Chromatic | Codrops Podium: Building a Website Where Running Becomes Storytelling | Codrops Designing Beyond the Surface: How DashDigital Turns Complexity into Clarity | Codrops Creative Entrepreneurship: Designing the Machine | Codrops Exploring 3D Image Rotations on Scroll | Codrops Always Building, Always Learning: Cyd Stumpel’s Journey Through the Modern Web | Codrops Designing A Better Lou: Reducing Cognitive Load Through Design, Content, and Systems | Codrops Sketching the Impossible: A 3D Portfolio Built Without a Single 3D Model | Codrops Building Horeca: Advanced Motion Design in Webflow Without the Performance Trade-Offs | Codrops Building an Interactive Digital Stamp Collection with Shaders, Postcards, and Playful Inspection | Codrops No Two Paths Alike: Inside San Rita’s Approach to Digital Experiences | Codrops The Making of the New Lesse Studio Website: Clarity, Performance, and Intentionality | Codrops Creating a Thumbnail Flow Animation with GSAP MotionPath | Codrops Forging Her Own Path: Houmahani Kane’s Journey in Creative Development | Codrops Beaucoup and the Pursuit of Memorable Experiences | Codrops The Future of Emotional Technology: Comfort Websites for Growth and Self-Awareness | Codrops The Never Ending Story: Building a Seamless Infinite Scroll Experience with GSAP & Lenis | Codrops Whooshes, Snaps and Shaders: Adrien Vanderpotte and the Feeling of the Interface | Codrops Building a Scroll-Driven 3D Cube Gallery in Webflow with GSAP | Codrops Creating Scroll-Driven SVG Map Animations with GSAP | Codrops Made With Gsap: Building a Fun Gravity-Based Mouse Trail | Codrops 80s Business Tech and Seamless Scene Transitions: Inside Shader.se’s Scroll-Driven WebGPU Pipeline | Codrops Merlin: The Code Boutique Turning Motion Into Digital Magic | Codrops Designing Ourselves: The New Obys Identity and Website | Codrops Exploring the HTML-in-Canvas Proposal | Codrops Le:mma Studio: Building the Feeling Behind the Screen | Codrops From Shader Uniforms to Clip-Path Wipes: How GSAP Drives My Portfolio | Codrops Akaru: Crafting Precision-Driven Digital Experiences | Codrops Designing Against the Gallery: A Two-Year Journey to a Layered Portfolio Experience | Codrops Between Human and Machine: Sofia Papadopoulou’s Approach to Augmented Creativity | Codrops More Than a Portfolio: Building a Scroll-Driven 3D World with Something to Say | Codrops Rhumb Studio: Small but Mighty, Shaped by Curiosity | Codrops Susurrus: Crafting a Cozy Watercolor World with Three.js and Shaders | Codrops Building 4WIDE: Turning Distortion, Blur, and Motion into a Coherent Experience | Codrops A Playful Clip Menu with GSAP’s easeReverse | Codrops False Earth: From WebGL Limits to a WebGPU-Driven World | Codrops Interactive Storytelling for the Web: Building Immersive Stories with Timelines, 3D, and Layered Scenes | Codrops The Art of Complex Motion: Corentin Bernadou’s World of Shaders and Experimentation | Codrops They Call Me Giulio: The Making of a Cinematic Cyberpunk Portfolio | Codrops Lusion: Where Digital Craft Meets Ambitious Experimentation | Codrops The Exat Microsite: Pushing a Typography Showcase to New Creative Extremes | Codrops A Single DM, a First SOTD, and the Start of Chanh M. Ho’s Creative Journey | Codrops Creating Custom Page Transitions in Astro with Barba.js and GSAP | Codrops R—K ’26: The Thinking and Code Behind a Portfolio Led by Presence | Codrops Building the Maxima Therapy Website: React, GSAP, and Dabbling with AI | Codrops Where Engineering Meets Craft: Edoardo Lunardi’s Obsession with the Details | Codrops Animating 160,000 Cubes in Three.js to Visualize Dithering | Codrops Arnaud Rocca’s Portfolio: From a GSAP-Powered Motion System to Fluid WebGL | Codrops Where Confidence Needs No Decoration: The Malvah.Studio Story | Codrops Motion Highlights #17 | Codrops
Reverse-Engineering Claude AI’s Mascot Animations with SVG and GSAP | Codrops
By Ayotomiwa Wale-Durojaye · 2026-05-05 · via Codrops

ClaudeAI posts animated clips of their mascot on social media. Short loops of their pixel mascot walking around and looking, waving a flag, working out, stomping with confetti. The timing has personality. The motion has weight. I just wanted to take them apart.

I slowed the clips to 0.3x, captured screenshots of every frame, illustrated the mascot, and rebuilt four animations from scratch in about four days. No video files, no GIFs. Just SVG, GSAP, and React. The goal was an exact replica, every timing, every easing, and every frame matching the original.

This is a breakdown of how I approached each one, the challenges I ran into, and how I pulled it off. You can have a look at the working examples here.

Four Claude Mascot Animations (source)

Tools

The mascot is built entirely from <rect> elements, no paths, no curves. Just rectangles arranged into a character. GSAP powers everything: gsap.to() for continuous tweened motion, gsap.set() for instant frame swaps, and gsap.timeline() to orchestrate sequences. Some animations are pure tweening. Others are frame-by-frame sprite sheets where each frame has its own hold time and certain sections of the sequence replay before continuing. One is a hybrid of both. React handles the component structure and refs.

Walking Claude

Walking Claude (source)

Walking Claude is the most complex of the four. The mascot looks around, jumps, walks across the screen, looks down, crouches, and leaps to the other side. It’s the only animation driven entirely by continuous GSAP tweens.

The Clip Mask

The first problem I ran into was the legs. When Claude leans to look around, the legs tilt and stretch using rotation and scaleY. That’s what gives the lean its weight. The legs are bending into the ground like they’re actually supporting the body. But stretching a rectangle doesn’t care about where the floor is. Without a boundary, the legs push right through.

Without Clip Mask

The fix is a <clipPath> wrapping the legs and cutting off anything that extends past the ground. Simple, but it’s the kind of detail that makes the difference between an animation that feels right and one that feels off.

With Clip Mask
<defs>
  <clipPath id="ground-clip">
    <rect x="-20" y="-50" width="160" height="136" />
  </clipPath>
</defs>

<g clipPath="url(#ground-clip)">
  <rect id="leg4" x="85" y="60" width="11" height="26" fill="#DD775B" />
  <rect id="leg3" x="64" y="60" width="11" height="26" fill="#DD775B" />
  <rect id="leg2" x="32" y="60" width="11" height="26" fill="#DD775B" />
  <rect id="leg1" x="11" y="60" width="11" height="26" fill="#DD775B" />
</g>

The lean. Getting the lean right was mostly about timing. GSAP’s "<" operator can sync multiple tweens to fire at the same time, so the eyes, body, and legs all move together in one beat. The body tilts, the eyes shift, and the legs stretch all at once, all with the same easing. That’s what makes it feel like one motion instead of three things happening separately.

tl.to(eyesRef.current, { x: -3, duration: 0.4, ease: "power2.out" })
  .to(bodyRef.current, { rotation: -3, x: -3, y: -5, 
    svgOrigin: "53 65", duration: 0.4, ease: "power2.out" }, "<")
  .to(legs, {
    rotation: (i) => [-7, -8, -8, -9][i],
    scaleY: (i) => [1.35, 1.3, 1.2, 1.15][i],
    duration: 0.4, ease: "power2.out"
  }, "<")

Each leg gets its own rotation and stretch value; the ones closer to the lean direction bend more. When it came to the walk, the legs needed to pivot from the hip instead of the feet. A .call() mid-timeline switches the svgOrigin before the walk starts, then switches back after. Same legs, different anchor point, completely different motion.

The Jump

The jump was the part where I went back to my screenshots. Claude crouches, launches across the screen in an arc, and bounces on landing. Getting the body, hands, and legs to all do the right thing at the right time meant studying the original frame by frame.

The crouch is quick, the body dips down and the hands drop with it, all in 0.1 seconds. That snap is what gives the “gathering momentum” feel before takeoff.

.to(bodyRef.current, { y: 8, duration: 0.1, ease: "power3.in" })
.to([leftHandRef.current, rightHandRef.current], 
  { y: 10, duration: 0.1, ease: "power3.in" }, "<")

Then the jump itself. The group moves horizontally while the vertical motion follows a parabolic arc — sine.out going up, power3.in coming down. The easing difference between up and down is what gives it natural gravity.

.to(groupRef.current, { x: "+=" + jumpDist, duration: 0.85, 
  ease: "power1.inOut" }, "jump")
.to(groupRef.current, { y: -90, duration: 0.42, 
  ease: "sine.out" }, "jump")
.to(groupRef.current, { y: 0, duration: 0.2, 
  ease: "power3.in" }, "jump+=0.6")
The Jump

The landing has a small bounce on the hands; they overshoot downwards for 0.05 seconds and then settle back up. Without it the landing feels stiff.

The Flag Waver

The Flag Waver (source)

Flag Waver is a hybrid: sprite frames for the flag and GSAP transforms for everything else. The flag can’t be tweened. The body sway, the hand movement, and the subtle shifts – those are all GSAP.

The Flag

I illustrated twelve versions of the flag, showing every position it takes mid-wave. Each frame is a different arrangement of 5×5 pixel rectangles, and there’s no shortcut. You can’t tween between pixel art shapes. You just draw them all. The first three frames are the flag rising, going from limp to fully catching the air. Once it’s up, the wave begins. So on the first play, the animation runs all twelve frames. After that, the loop picks up from frame four. The flag is already in the air. It doesn’t need to rise again.

Flag Sprites

Attaching the flag to the hand

I wrapped the right hand and all twelve flag sprites inside a single <g> element so they share the same transform. Wherever the hand goes, the flag follows. The hand also had to move in the opposite direction of the flag wave; as the flag swings out, the hand pulls back to meet it, keeping the flag attached to the wrist instead of drifting away.

const handExtraX = [0, -6, -12, -14, -8, -2, 0, 0, -4, -10, -16, -18];

tl.set(handGroup, { x: handExtraX[frame] }, time);
<g ref={handGroupRef}>
  <rect id="right-hand" x="92" y="46" width="21.6589" height="22.6434" fill="#DD775B" />
  <g ref={el => (frameRefs.current[0] = el)}>{/* flag frame 0 */}</g>
  <g ref={el => (frameRefs.current[1] = el)}>{/* flag frame 1 */}</g>
  {/* ...all 12 */}
</g>
Hand Moving with Sprites

The Body

The body had to move opposite to the flag. When the flag swings right, the mascot shifts left. When it comes back, he shifts right. The feet stay planted the whole time; only the upper body sways. I mapped each frame to a sway value:

const swayX = [0, 0, -5, -5, 0, 4, 4, 4, 0, 0, -5, -5];

The left hand follows the same idea. When the body shifts left, the left hand drops a few pixels with it. Just 4 pixels on certain frames:

const leftHandY = [0, 0, 4, 4, 0, 0, 0, 0, 0, 0, 4, 4];

Confetti Claude

Confetti Claude (source)

Confetti Claude is three animations running at the same time. The character is stomping, and two confetti bursts are firing independently.

The Character

Eight frames of Claude stomping: tilting left, reaching up, tilting right, reaching up again. Again, each frame is a completely different illustration. The body shape changes, the hand positions change, and the leg heights change. GSAP steps through the eight frames on a 125ms loop.

Jumping Sprites

The Confett

Eight sprites, completely separate from the character. Each frame is a different scatter of colored pixels; they spread out wide at first, then thin out as the burst fades until there’s nothing left. The whole burst also moves through the air, shoots up, peaks, and falls back down. Eight Y values doing the work:

const particleYOffsets = [-65, -72, -76, -70, -58, -42, -22, 0];
Confetti

The Timing

The confetti doesn’t just play on its own. It waits for the mascot’s hand to reach the top of the stomp before it fires. The first burst starts with a one-frame delay, so it lines up with leg frame 1, the exact moment the hand is raised. The second burst fires at the last leg frame, the opposite stomp:

const pTl = gsap.timeline({ repeat: -1, delay: FRAME_DURATION });
const p2Tl = gsap.timeline({ repeat: -1, delay: 6 * FRAME_DURATION });

Three timelines are running independently, but they stay in sync because the delays line up with the stomp cycle. The result is that it looks like Claude is actually throwing the confetti; the hand goes up, and the burst follows. The second burst uses the same sprites mirrored with scale(-1, 1), launching from the left side instead of the right.

Gym Claude

Gym Claude (source)

Gym Claude looks like the simplest animation, but it was actually the hardest. There’s no tweening, no transforms, no computed values. Just 36 illustrated frames every position of Claude picking up the dumbbell, curling it overhead, and putting it back down. Each frame is a completely different SVG illustration. 36 frames are drawn, but the playback sequence runs through 48 beats because frames 13 through 24 play twice. Claude does a second rep.

Gym Claude with timing

The work wasn’t mainly in the code. It was in drawing every single frame and getting the timing right between them. Not every frame plays at the same speed. Some need to hold longer; the dumbbell pauses at the top of the curl, and the mascot holds position before the next rep. A flat rate makes it feel like a slideshow. Dynamic delays give it rhythm. GSAP builds the whole sequence as a single timeline. It loops through the frame array, sets each frame’s visibility, and places it on the timeline at the right moment using the delay values:

function getDelay(seqIdx, frame) {
  if (seqIdx === frameSequence.length - 1) return 1.5;
  if (frame === 6 || frame === 7) return 0.27;
  if (frame === 15) return 0.4;
  if (frame === 21) return 0.4;
  return 0.085;
}

const tl = gsap.timeline({ repeat: -1 });
let time = 0;

for (let i = 0; i < frameSequence.length; i++) {
  const frame = frameSequence[i];
  frames.forEach((el, j) => {
    if (el) tl.set(el, { display: j === frame ? "inline" : "none" }, time);
  });
  time += getDelay(i, frame);
}

Frames 6 and 7 hold for 270 ms, that’s the effort at the top of the lift. Frames 15 and 21 hold for 400ms; the pause between reps. The last frame sits for a full 1.5 seconds before the whole thing loops. Small differences, but they’re what make it feel like Claude is actually working out and not just cycling through SVGs.

Reflections

The whole project took about four days. What kept me going was having a clear picture of the result in my head, the goal was an exact replica of the original animations. Not “inspired by,” not “similar to.” The same thing. That meant every timing, every easing, every frame had to match. It was a specific kind of challenge, reverse-engineering someone else’s creative decisions with code.

Shout out to GSAP for making this kind of work possible, and for the merch bundle I won after posting this project. And to ClaudeAI for the original animations that started the whole thing.

Thanks for reading!! If you made it this far, I hope something here sparked an idea. Go build something, your corner of the web should be fun.