Appearance
Interactive Examples Gallery
Browse, scrub, and remix exact SVG frames generated by the anim engine. Every example is a tiny animated scene — rockets, frogs, ghosts, jellyfish, campfires — built from the same handful of shapes and signals you get on day one. Each one runs at least three seconds at 60 FPS, so open the source, change a color or a number, and make it yours.
Shapes & Motion
01. Pixel Rocket Liftoff
Live canvas01. Pixel Rocket Liftoff
400 × 30060 fps
Loading renderer…
Rendered SVG01. Pixel Rocket Liftoff
Loading rendered frames…
anim
// Stacked rectangles blast a pixel-art rocket off the launch pad.
let sky = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #0b1026),
rect(x: 60px, y: 46px, width: 4px, height: 4px, fill: #fbcfe8),
rect(x: 150px, y: 30px, width: 4px, height: 4px, fill: #a5b4fc),
rect(x: 300px, y: 58px, width: 4px, height: 4px, fill: #fde68a),
rect(x: 344px, y: 108px, width: 4px, height: 4px, fill: #a5b4fc),
rect(x: 96px, y: 96px, width: 4px, height: 4px, fill: #fde68a),
rect(x: 40px, y: 262px, width: 320px, height: 38px, fill: #1f2937),
rect(x: 176px, y: 250px, width: 48px, height: 14px, fill: #374151)
]);
let base = step(before: sky, after: sky, at: 0s);
let lift = tween(from: 250px, to: 96px, start: 0s, end: 1.6s, easing: cubic_bezier(x1: 0.3, y1: 0, x2: 0.5, y2: 1));
let settle = tween(from: 96px, to: 250px, start: 0s, end: 1.4s, easing: cubic_bezier(x1: 0.4, y1: 0, x2: 0.7, y2: 1));
let rocket_y = sequence(first: lift, second: settle, at: 1.6s);
let flame_up = tween(from: 0.6, to: 1.4, start: 0s, end: 0.16s);
let flame_dn = tween(from: 1.4, to: 0.6, start: 0s, end: 0.16s);
let flicker = repeat(signal: sequence(first: flame_up, second: flame_dn, at: 0.16s), every: 0.32s);
let flame = translate(x: 200px, y: rocket_y, scene: scale(x: 1.0, y: flicker, scene: stack(children: [
rect(x: -11px, y: 0px, width: 22px, height: 22px, fill: #fbbf24),
rect(x: -6px, y: 0px, width: 12px, height: 34px, fill: #fb7185)
])));
let rocket = translate(x: 200px, y: rocket_y, scene: stack(children: [
rect(x: -16px, y: -70px, width: 32px, height: 70px, fill: #e2e8f0),
rect(x: -16px, y: -84px, width: 32px, height: 16px, fill: #f43f5e),
rect(x: -8px, y: -52px, width: 16px, height: 16px, fill: #38bdf8),
rect(x: -30px, y: -22px, width: 14px, height: 22px, fill: #f43f5e),
rect(x: 16px, y: -22px, width: 14px, height: 22px, fill: #f43f5e)
]));
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [base, flame, rocket]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png02. Aquarium Bubbles
Live canvas02. Aquarium Bubbles
400 × 30060 fps
Loading renderer…
Rendered SVG02. Aquarium Bubbles
Loading rendered frames…
anim
// Ellipses become bubbles drifting up past a curious aquarium fish.
let tank = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #052e3a),
rounded_rect(x: 46px, y: 40px, width: 308px, height: 220px, rx: 26px, ry: 26px, fill: #063f52),
ellipse(x: 236px, y: 118px, width: 96px, height: 64px, fill: #f59e0b),
triangle(x1: 236px, y1: 150px, x2: 300px, y2: 122px, x3: 300px, y3: 178px, fill: #f59e0b),
ellipse(x: 292px, y: 138px, width: 16px, height: 16px, fill: #0b1026),
ellipse(x: 296px, y: 142px, width: 6px, height: 6px, fill: #ffffff)
]);
let base = step(before: tank, after: tank, at: 0s);
let up = tween(from: 0px, to: -30px, start: 0s, end: 0.75s, easing: cubic_bezier(x1: 0.4, y1: 0, x2: 0.6, y2: 1));
let dn = tween(from: -30px, to: 0px, start: 0s, end: 0.75s, easing: cubic_bezier(x1: 0.4, y1: 0, x2: 0.6, y2: 1));
let bob = repeat(signal: sequence(first: up, second: dn, at: 0.75s), every: 1.5s);
let b1 = translate(x: 108px, y: 158px + bob, scene: stack(children: [
ellipse(x: -17px, y: -17px, width: 34px, height: 34px, fill: #7dd3fc),
ellipse(x: -10px, y: -12px, width: 10px, height: 10px, fill: #ffffff)
]));
let b2 = translate(x: 152px, y: 176px - bob * 0.7, scene: stack(children: [
ellipse(x: -11px, y: -11px, width: 22px, height: 22px, fill: #bae6fd),
ellipse(x: -6px, y: -8px, width: 7px, height: 7px, fill: #ffffff)
]));
let b3 = translate(x: 132px, y: 128px + bob * 0.5, scene: ellipse(x: -8px, y: -8px, width: 16px, height: 16px, fill: #e0f2fe));
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [base, b1, b2, b3]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png03. Friendly Robot Pop-In
Live canvas03. Friendly Robot Pop-In
400 × 30060 fps
Loading renderer…
Rendered SVG03. Friendly Robot Pop-In
Loading rendered frames…
anim
// Rounded rectangles assemble a friendly robot that pops onto the screen.
let base_scene = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #0b1220),
rounded_rect(x: 66px, y: 60px, width: 268px, height: 180px, rx: 28px, ry: 28px, fill: #111827)
]);
let base = step(before: base_scene, after: base_scene, at: 0s);
let enter = tween(from: -250px, to: 0px, start: 0s, end: 1s, easing: cubic_bezier(x1: 0.2, y1: 0.9, x2: 0.3, y2: 1.0));
let settle = tween(from: 0px, to: 12px, start: 0s, end: 2s);
let slide = sequence(first: enter, second: settle, at: 1s);
let robot = translate(x: slide, y: 0px, scene: stack(children: [
rounded_rect(x: 194px, y: 46px, width: 12px, height: 30px, rx: 6px, ry: 6px, fill: #64748b),
ellipse(x: 189px, y: 34px, width: 22px, height: 22px, fill: #fbbf24),
rounded_rect(x: 96px, y: 72px, width: 208px, height: 138px, rx: 32px, ry: 32px, fill: #38bdf8),
rounded_rect(x: 122px, y: 104px, width: 52px, height: 62px, rx: 18px, ry: 18px, fill: #0f172a),
rounded_rect(x: 226px, y: 104px, width: 52px, height: 62px, rx: 18px, ry: 18px, fill: #0f172a),
rounded_rect(x: 135px, y: 122px, width: 22px, height: 26px, rx: 9px, ry: 9px, fill: #a7f3d0),
rounded_rect(x: 239px, y: 122px, width: 22px, height: 26px, rx: 9px, ry: 9px, fill: #a7f3d0),
rounded_rect(x: 156px, y: 182px, width: 88px, height: 16px, rx: 8px, ry: 8px, fill: #0f172a)
]));
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [base, robot]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png04. Pinwheel in the Breeze
Live canvas04. Pinwheel in the Breeze
400 × 30060 fps
Loading renderer…
Rendered SVG04. Pinwheel in the Breeze
Loading rendered frames…
anim
// Triangles spin a bright pinwheel in the summer breeze.
let base_scene = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #bae6fd),
ellipse(x: 40px, y: 40px, width: 70px, height: 70px, fill: #fef9c3),
rect(x: 0px, y: 236px, width: 400px, height: 64px, fill: #86efac),
rect(x: 196px, y: 140px, width: 8px, height: 108px, fill: #92400e)
]);
let base = step(before: base_scene, after: base_scene, at: 0s);
let linear_curve = cubic_bezier(x1: 0, y1: 0, x2: 1, y2: 1);
let spin = keyframes(frames: [
{time: 0s, value: 0deg, easing: linear_curve, hold: false},
{time: 3s, value: 320deg, easing: linear_curve, hold: false}
]);
let pinwheel = translate(x: 200px, y: 140px, scene: rotate(angle: spin, scene: stack(children: [
triangle(x1: 0px, y1: 0px, x2: 62px, y2: -20px, x3: 20px, y3: -62px, fill: #f43f5e),
triangle(x1: 0px, y1: 0px, x2: -20px, y2: -62px, x3: -62px, y3: -20px, fill: #fbbf24),
triangle(x1: 0px, y1: 0px, x2: -62px, y2: 20px, x3: -20px, y3: 62px, fill: #34d399),
triangle(x1: 0px, y1: 0px, x2: 20px, y2: 62px, x3: 62px, y3: 20px, fill: #38bdf8)
])));
let hub_scene = translate(x: 200px, y: 140px, scene: ellipse(x: -9px, y: -9px, width: 18px, height: 18px, fill: #1f2937));
let hub = step(before: hub_scene, after: hub_scene, at: 0s);
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [base, pinwheel, hub]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png05. Stack of Pancakes
Live canvas05. Stack of Pancakes
400 × 30060 fps
Loading renderer…
Rendered SVG05. Stack of Pancakes
Loading rendered frames…
anim
// Painter order stacks pancakes; the top flapjack flips up to show it is on top.
let base_scene = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #2a1a12),
rounded_rect(x: 92px, y: 214px, width: 216px, height: 26px, rx: 13px, ry: 13px, fill: #3b2416),
ellipse(x: 112px, y: 150px, width: 176px, height: 52px, fill: #d9a441),
ellipse(x: 104px, y: 176px, width: 192px, height: 56px, fill: #e0b04a)
]);
let base = step(before: base_scene, after: base_scene, at: 0s);
let lift = tween(from: 0px, to: -52px, start: 0s, end: 1.5s, easing: cubic_bezier(x1: 0.3, y1: 0, x2: 0.4, y2: 1));
let drop = tween(from: -52px, to: 0px, start: 0s, end: 1.5s, easing: cubic_bezier(x1: 0.4, y1: 0, x2: 0.6, y2: 1));
let hop = sequence(first: lift, second: drop, at: 1.5s);
let top = translate(x: 0px, y: hop, scene: stack(children: [
ellipse(x: 98px, y: 118px, width: 204px, height: 58px, fill: #f0c060),
ellipse(x: 150px, y: 104px, width: 100px, height: 30px, fill: #7c3f12),
ellipse(x: 208px, y: 116px, width: 34px, height: 22px, fill: #7c3f12),
rounded_rect(x: 176px, y: 96px, width: 40px, height: 22px, rx: 6px, ry: 6px, fill: #facc15)
]));
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [base, top]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png06. Pick-a-Balloon Stand
Live canvas06. Pick-a-Balloon Stand
400 × 30060 fps
Loading renderer…
Rendered SVG06. Pick-a-Balloon Stand
Loading rendered frames…
anim
// A balloon stand: the chosen balloon swells while its friends wait.
let base_scene = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #0b1220),
rounded_rect(x: 34px, y: 236px, width: 332px, height: 40px, rx: 12px, ry: 12px, fill: #1f2937)
]);
let base = step(before: base_scene, after: base_scene, at: 0s);
let balloon(cx, c) = translate(x: cx, y: 148px, scene: stack(children: [
rect(x: -1px, y: 44px, width: 2px, height: 76px, fill: #475569),
ellipse(x: -26px, y: -34px, width: 52px, height: 66px, fill: c),
ellipse(x: -13px, y: -24px, width: 13px, height: 18px, fill: #ffffff66)
]));
let others_scene = stack(children: [
balloon(cx: 80px, c: #f43f5e),
balloon(cx: 140px, c: #fbbf24),
balloon(cx: 260px, c: #34d399),
balloon(cx: 320px, c: #38bdf8)
]);
let others = step(before: others_scene, after: others_scene, at: 0s);
let grow = tween(from: 0.8, to: 1.35, start: 0s, end: 1.5s);
let shrink = tween(from: 1.35, to: 0.8, start: 0s, end: 1.5s);
let chosen = sequence(first: grow, second: shrink, at: 1.5s);
let hero = translate(x: 200px, y: 148px, scene: scale(x: chosen, y: chosen, scene: stack(children: [
rect(x: -1px, y: 44px, width: 2px, height: 76px, fill: #475569),
ellipse(x: -26px, y: -34px, width: 52px, height: 66px, fill: #a855f7),
ellipse(x: -13px, y: -24px, width: 13px, height: 18px, fill: #ffffff66)
])));
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [base, others, hero]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png07. Frog and Lily Pads
Live canvas07. Frog and Lily Pads
400 × 30060 fps
Loading renderer…
Rendered SVG07. Frog and Lily Pads
Loading rendered frames…
anim
// Nested stacks build two lily pads; a frog leaps back and forth between them.
let pond = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #0c4a6e),
rect(x: 0px, y: 70px, width: 400px, height: 26px, fill: #0e5a80),
stack(children: [
ellipse(x: 44px, y: 198px, width: 120px, height: 54px, fill: #166534),
triangle(x1: 104px, y1: 225px, x2: 60px, y2: 250px, x3: 92px, y3: 214px, fill: #0c4a6e),
ellipse(x: 88px, y: 208px, width: 22px, height: 22px, fill: #f472b6)
]),
stack(children: [
ellipse(x: 236px, y: 198px, width: 120px, height: 54px, fill: #15803d),
triangle(x1: 296px, y1: 225px, x2: 252px, y2: 250px, x3: 284px, y3: 214px, fill: #0c4a6e),
ellipse(x: 280px, y: 208px, width: 22px, height: 22px, fill: #fbbf24)
])
]);
let base = step(before: pond, after: pond, at: 0s);
let hop_right = tween(from: 104px, to: 296px, start: 0s, end: 1.5s, easing: cubic_bezier(x1: 0.3, y1: 0, x2: 0.7, y2: 1));
let hop_left = tween(from: 296px, to: 104px, start: 0s, end: 1.5s, easing: cubic_bezier(x1: 0.3, y1: 0, x2: 0.7, y2: 1));
let frog_x = sequence(first: hop_right, second: hop_left, at: 1.5s);
let arc_up = tween(from: 0px, to: -72px, start: 0s, end: 0.75s, easing: cubic_bezier(x1: 0.2, y1: 0.8, x2: 0.4, y2: 1));
let arc_down = tween(from: -72px, to: 0px, start: 0s, end: 0.75s, easing: cubic_bezier(x1: 0.6, y1: 0, x2: 0.8, y2: 1));
let frog_y = repeat(signal: sequence(first: arc_up, second: arc_down, at: 0.75s), every: 1.5s);
let frog = translate(x: frog_x, y: 196px + frog_y, scene: stack(children: [
ellipse(x: -24px, y: -18px, width: 48px, height: 32px, fill: #4ade80),
ellipse(x: -20px, y: -30px, width: 16px, height: 16px, fill: #4ade80),
ellipse(x: 4px, y: -30px, width: 16px, height: 16px, fill: #4ade80),
ellipse(x: -17px, y: -28px, width: 8px, height: 8px, fill: #0b1026),
ellipse(x: 9px, y: -28px, width: 8px, height: 8px, fill: #0b1026),
ellipse(x: -18px, y: 10px, width: 12px, height: 8px, fill: #16a34a),
ellipse(x: 6px, y: 10px, width: 12px, height: 8px, fill: #16a34a)
]));
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [base, frog]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png08. Bee Visits the Flowers
Live canvas08. Bee Visits the Flowers
400 × 30060 fps
Loading renderer…
Rendered SVG08. Bee Visits the Flowers
Loading rendered frames…
anim
// Translation flies a fuzzy little bee from flower to flower.
let flower(cx) = stack(children: [
rect(x: cx - 2px, y: 214px, width: 4px, height: 44px, fill: #15803d),
ellipse(x: cx - 18px, y: 188px, width: 36px, height: 36px, fill: #f472b6),
ellipse(x: cx - 9px, y: 197px, width: 18px, height: 18px, fill: #fde047)
]);
let meadow = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #bae6fd),
ellipse(x: 300px, y: 34px, width: 66px, height: 66px, fill: #fef9c3),
rect(x: 0px, y: 236px, width: 400px, height: 64px, fill: #86efac),
flower(cx: 90px),
flower(cx: 200px),
flower(cx: 310px)
]);
let base = step(before: meadow, after: meadow, at: 0s);
let fly_out = tween(from: 90px, to: 310px, start: 0s, end: 1.5s, easing: cubic_bezier(x1: 0.4, y1: 0, x2: 0.6, y2: 1));
let fly_back = tween(from: 310px, to: 90px, start: 0s, end: 1.5s, easing: cubic_bezier(x1: 0.4, y1: 0, x2: 0.6, y2: 1));
let bee_x = sequence(first: fly_out, second: fly_back, at: 1.5s);
let flutter_up = tween(from: 0px, to: -13px, start: 0s, end: 0.25s);
let flutter_down = tween(from: -13px, to: 0px, start: 0s, end: 0.25s);
let flutter = repeat(signal: sequence(first: flutter_up, second: flutter_down, at: 0.25s), every: 0.5s);
let bee = translate(x: bee_x, y: 150px + flutter, scene: stack(children: [
ellipse(x: -22px, y: -9px, width: 22px, height: 16px, fill: #e0f2fe),
ellipse(x: 2px, y: -9px, width: 22px, height: 16px, fill: #e0f2fe),
ellipse(x: -15px, y: -11px, width: 30px, height: 22px, fill: #fbbf24),
rect(x: -7px, y: -11px, width: 5px, height: 22px, fill: #1f2937),
rect(x: 3px, y: -11px, width: 5px, height: 22px, fill: #1f2937),
ellipse(x: 12px, y: -8px, width: 12px, height: 12px, fill: #1f2937),
ellipse(x: 16px, y: -6px, width: 4px, height: 4px, fill: #ffffff)
]));
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [base, bee]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png09. Jiggly Bowl of Jello
Live canvas09. Jiggly Bowl of Jello
400 × 30060 fps
Loading renderer…
Rendered SVG09. Jiggly Bowl of Jello
Loading rendered frames…
anim
// Non-uniform scale wobbles a jiggly bowl of jello on its plate.
let base_scene = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #1e1b2e),
ellipse(x: 118px, y: 230px, width: 164px, height: 24px, fill: #3b0764),
rounded_rect(x: 116px, y: 222px, width: 168px, height: 16px, rx: 8px, ry: 8px, fill: #cbd5e1)
]);
let base = step(before: base_scene, after: base_scene, at: 0s);
let squash = cubic_bezier(x1: 0.4, y1: 0, x2: 0.6, y2: 1);
let wide = tween(from: 0.86, to: 1.16, start: 0s, end: 0.5s, easing: squash);
let narrow = tween(from: 1.16, to: 0.86, start: 0s, end: 0.5s, easing: squash);
let sx = repeat(signal: sequence(first: wide, second: narrow, at: 0.5s), every: 1s);
let short = tween(from: 1.16, to: 0.86, start: 0s, end: 0.5s, easing: squash);
let tall = tween(from: 0.86, to: 1.16, start: 0s, end: 0.5s, easing: squash);
let sy = repeat(signal: sequence(first: short, second: tall, at: 0.5s), every: 1s);
let jello = translate(x: 200px, y: 222px, scene: scale(x: sx, y: sy, scene: stack(children: [
rounded_rect(x: -58px, y: -86px, width: 116px, height: 86px, rx: 40px, ry: 40px, fill: #fb7185),
rounded_rect(x: -58px, y: -86px, width: 116px, height: 40px, rx: 40px, ry: 40px, fill: #fda4af),
ellipse(x: -30px, y: -74px, width: 20px, height: 12px, fill: #ffe4e6),
ellipse(x: -20px, y: -44px, width: 9px, height: 11px, fill: #7f1d1d),
ellipse(x: 11px, y: -44px, width: 9px, height: 11px, fill: #7f1d1d),
ellipse(x: -8px, y: -30px, width: 16px, height: 8px, fill: #7f1d1d)
])));
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [base, jello]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png10. Spinning Beach Ball
Live canvas10. Spinning Beach Ball
400 × 30060 fps
Loading renderer…
Rendered SVG10. Spinning Beach Ball
Loading rendered frames…
anim
// Rotation spins a colorful beach ball on the warm sand.
let base_scene = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #7dd3fc),
rect(x: 0px, y: 236px, width: 400px, height: 64px, fill: #fcd34d),
ellipse(x: 146px, y: 244px, width: 108px, height: 18px, fill: #eab308)
]);
let base = step(before: base_scene, after: base_scene, at: 0s);
let linear_curve = cubic_bezier(x1: 0, y1: 0, x2: 1, y2: 1);
let spin = keyframes(frames: [
{time: 0s, value: 0deg, easing: linear_curve, hold: false},
{time: 3s, value: 320deg, easing: linear_curve, hold: false}
]);
let ball = translate(x: 200px, y: 168px, scene: rotate(angle: spin, scene: stack(children: [
ellipse(x: -70px, y: -70px, width: 140px, height: 140px, fill: #f8fafc),
triangle(x1: 0px, y1: 0px, x2: 66px, y2: -22px, x3: 22px, y3: -66px, fill: #f43f5e),
triangle(x1: 0px, y1: 0px, x2: -22px, y2: -66px, x3: -66px, y3: -22px, fill: #38bdf8),
triangle(x1: 0px, y1: 0px, x2: -66px, y2: 22px, x3: -22px, y3: 66px, fill: #fbbf24),
triangle(x1: 0px, y1: 0px, x2: 22px, y2: 66px, x3: 66px, y3: 22px, fill: #34d399),
ellipse(x: -13px, y: -13px, width: 26px, height: 26px, fill: #f8fafc)
])));
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [base, ball]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png11. Dancing Desert Cactus
Live canvas11. Dancing Desert Cactus
400 × 30060 fps
Loading renderer…
Rendered SVG11. Dancing Desert Cactus
Loading rendered frames…
anim
// Chained translate, rotate, and scale make a happy cactus dance in the desert.
let side_cactus(cx) = stack(children: [
rounded_rect(x: cx - 11px, y: 150px, width: 22px, height: 86px, rx: 11px, ry: 11px, fill: #166534),
rounded_rect(x: cx - 27px, y: 178px, width: 18px, height: 14px, rx: 7px, ry: 7px, fill: #166534),
rounded_rect(x: cx + 9px, y: 178px, width: 18px, height: 14px, rx: 7px, ry: 7px, fill: #166534)
]);
let base_scene = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #fdba74),
ellipse(x: 60px, y: 40px, width: 60px, height: 60px, fill: #fef3c7),
rect(x: 0px, y: 236px, width: 400px, height: 64px, fill: #f59e0b),
side_cactus(cx: 66px),
side_cactus(cx: 334px)
]);
let base = step(before: base_scene, after: base_scene, at: 0s);
let smooth = cubic_bezier(x1: 0.4, y1: 0, x2: 0.6, y2: 1);
let tilt = keyframes(frames: [
{time: 0s, value: -12deg, easing: smooth, hold: false},
{time: 1.5s, value: 12deg, easing: smooth, hold: false},
{time: 3s, value: -12deg, easing: smooth, hold: false}
]);
let zoom_in = tween(from: 0.92, to: 1.12, start: 0s, end: 1.5s);
let zoom_out = tween(from: 1.12, to: 0.92, start: 0s, end: 1.5s);
let zoom = sequence(first: zoom_in, second: zoom_out, at: 1.5s);
let dancer = translate(x: 200px, y: 226px, scene: rotate(angle: tilt, scene: scale(x: zoom, y: zoom, scene: stack(children: [
rounded_rect(x: -16px, y: -104px, width: 32px, height: 104px, rx: 16px, ry: 16px, fill: #22c55e),
rounded_rect(x: -38px, y: -74px, width: 24px, height: 16px, rx: 8px, ry: 8px, fill: #22c55e),
rounded_rect(x: -38px, y: -90px, width: 16px, height: 22px, rx: 8px, ry: 8px, fill: #22c55e),
rounded_rect(x: 14px, y: -64px, width: 24px, height: 16px, rx: 8px, ry: 8px, fill: #22c55e),
rounded_rect(x: 22px, y: -80px, width: 16px, height: 22px, rx: 8px, ry: 8px, fill: #22c55e),
ellipse(x: -9px, y: -82px, width: 7px, height: 8px, fill: #0b1026),
ellipse(x: 3px, y: -82px, width: 7px, height: 8px, fill: #0b1026),
ellipse(x: -7px, y: -68px, width: 14px, height: 7px, fill: #14532d)
]))));
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [base, dancer]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png12. Peekaboo Ghost
Live canvas12. Peekaboo Ghost
400 × 30060 fps
Loading renderer…
Rendered SVG12. Peekaboo Ghost
Loading rendered frames…
anim
// Group opacity floats a friendly ghost that fades in and out for peekaboo.
let room = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #0b1026),
ellipse(x: 296px, y: 34px, width: 58px, height: 58px, fill: #fde68a),
ellipse(x: 74px, y: 60px, width: 5px, height: 5px, fill: #fef9c3),
ellipse(x: 150px, y: 44px, width: 4px, height: 4px, fill: #fef9c3),
rounded_rect(x: 40px, y: 214px, width: 320px, height: 58px, rx: 16px, ry: 16px, fill: #111827)
]);
let base = step(before: room, after: room, at: 0s);
let bob_up = tween(from: 0px, to: -16px, start: 0s, end: 1s, easing: cubic_bezier(x1: 0.4, y1: 0, x2: 0.6, y2: 1));
let bob_down = tween(from: -16px, to: 0px, start: 0s, end: 1s, easing: cubic_bezier(x1: 0.4, y1: 0, x2: 0.6, y2: 1));
let bob = repeat(signal: sequence(first: bob_up, second: bob_down, at: 1s), every: 2s);
let fade_in = tween(from: 0.0, to: 1.0, start: 0s, end: 1s);
let fade_out = tween(from: 1.0, to: 0.0, start: 0s, end: 2s);
let alpha = sequence(first: fade_in, second: fade_out, at: 1s);
let ghost = opacity(value: alpha, scene: translate(x: 200px, y: 150px + bob, scene: stack(children: [
rounded_rect(x: -44px, y: -70px, width: 88px, height: 116px, rx: 44px, ry: 44px, fill: #f8fafc),
rect(x: -44px, y: -18px, width: 88px, height: 58px, fill: #f8fafc),
triangle(x1: -44px, y1: 40px, x2: -22px, y2: 40px, x3: -33px, y3: 58px, fill: #f8fafc),
triangle(x1: -22px, y1: 40px, x2: 0px, y2: 40px, x3: -11px, y3: 58px, fill: #f8fafc),
triangle(x1: 0px, y1: 40px, x2: 22px, y2: 40px, x3: 11px, y3: 58px, fill: #f8fafc),
triangle(x1: 22px, y1: 40px, x2: 44px, y2: 40px, x3: 33px, y3: 58px, fill: #f8fafc),
ellipse(x: -22px, y: -34px, width: 15px, height: 20px, fill: #0b1026),
ellipse(x: 7px, y: -34px, width: 15px, height: 20px, fill: #0b1026),
ellipse(x: -9px, y: -6px, width: 18px, height: 12px, fill: #fbcfe8)
])));
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [base, ghost]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png13. Moon Orbiting a Planet
Live canvas13. Moon Orbiting a Planet
400 × 30060 fps
Loading renderer…
Rendered SVG13. Moon Orbiting a Planet
Loading rendered frames…
anim
// Coordinated translation swings a little moon around a grinning planet.
let base_scene = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #020617),
ellipse(x: 60px, y: 50px, width: 5px, height: 5px, fill: #fef9c3),
ellipse(x: 330px, y: 70px, width: 4px, height: 4px, fill: #fef9c3),
ellipse(x: 120px, y: 250px, width: 4px, height: 4px, fill: #fef9c3),
ellipse(x: 150px, y: 100px, width: 100px, height: 100px, fill: #38bdf8),
ellipse(x: 176px, y: 128px, width: 14px, height: 16px, fill: #0b1026),
ellipse(x: 210px, y: 128px, width: 14px, height: 16px, fill: #0b1026),
ellipse(x: 176px, y: 150px, width: 48px, height: 30px, fill: #0f172a),
ellipse(x: 176px, y: 142px, width: 48px, height: 30px, fill: #38bdf8)
]);
let base = step(before: base_scene, after: base_scene, at: 0s);
let x_right = sequence(first: tween(from: 0px, to: 105px, start: 0s, end: 0.75s), second: tween(from: 105px, to: 0px, start: 0s, end: 0.75s), at: 0.75s);
let x_left = sequence(first: tween(from: 0px, to: -105px, start: 0s, end: 0.75s), second: tween(from: -105px, to: 0px, start: 0s, end: 0.75s), at: 0.75s);
let orbit_x = sequence(first: x_right, second: x_left, at: 1.5s);
let y_down = sequence(first: tween(from: -70px, to: 0px, start: 0s, end: 0.75s), second: tween(from: 0px, to: 70px, start: 0s, end: 0.75s), at: 0.75s);
let y_up = sequence(first: tween(from: 70px, to: 0px, start: 0s, end: 0.75s), second: tween(from: 0px, to: -70px, start: 0s, end: 0.75s), at: 0.75s);
let orbit_y = sequence(first: y_down, second: y_up, at: 1.5s);
let moon = translate(x: 200px + orbit_x, y: 150px + orbit_y, scene: stack(children: [
ellipse(x: -16px, y: -16px, width: 32px, height: 32px, fill: #e2e8f0),
ellipse(x: -8px, y: -6px, width: 9px, height: 9px, fill: #cbd5e1),
ellipse(x: 3px, y: 3px, width: 6px, height: 6px, fill: #cbd5e1)
]));
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [base, moon]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png14. Train Window View
Live canvas14. Train Window View
400 × 30060 fps
Loading renderer…
Rendered SVG14. Train Window View
Loading rendered frames…
anim
// A rectangular clip becomes a train window with the countryside rolling past.
let shell_scene = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #0b1220),
rounded_rect(x: 96px, y: 44px, width: 208px, height: 212px, rx: 26px, ry: 26px, fill: #334155),
rounded_rect(x: 112px, y: 60px, width: 176px, height: 180px, rx: 14px, ry: 14px, fill: #1e293b)
]);
let shell = step(before: shell_scene, after: shell_scene, at: 0s);
let out = tween(from: -110px, to: 110px, start: 0s, end: 1.5s);
let back = tween(from: 110px, to: -110px, start: 0s, end: 1.5s);
let sweep = sequence(first: out, second: back, at: 1.5s);
let scenery = translate(x: sweep, y: 0px, scene: stack(children: [
rect(x: 40px, y: 64px, width: 320px, height: 172px, fill: #7dd3fc),
ellipse(x: 250px, y: 78px, width: 46px, height: 46px, fill: #fde047),
ellipse(x: 10px, y: 176px, width: 170px, height: 130px, fill: #34d399),
ellipse(x: 176px, y: 190px, width: 210px, height: 130px, fill: #22c55e),
ellipse(x: 118px, y: 96px, width: 38px, height: 46px, fill: #f43f5e),
rect(x: 132px, y: 140px, width: 10px, height: 12px, fill: #78350f)
]));
let window = clip(x: 116px, y: 64px, width: 168px, height: 172px, scene: scenery);
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [shell, window]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png15. Star-Shaped Galaxy Peek
Live canvas15. Star-Shaped Galaxy Peek
400 × 30060 fps
Loading renderer…
Rendered SVG15. Star-Shaped Galaxy Peek
Loading rendered frames…
anim
// An alpha mask cuts a star-shaped window that drifts across a galaxy.
let base_scene = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #0b1220),
ellipse(x: 70px, y: 60px, width: 5px, height: 5px, fill: #e2e8f0),
ellipse(x: 330px, y: 90px, width: 4px, height: 4px, fill: #e2e8f0),
ellipse(x: 300px, y: 240px, width: 5px, height: 5px, fill: #e2e8f0)
]);
let base = step(before: base_scene, after: base_scene, at: 0s);
let rim_scene = stack(children: [
triangle(x1: 200px, y1: 52px, x2: 144px, y2: 206px, x3: 256px, y3: 206px, fill: #fbbf24),
triangle(x1: 200px, y1: 248px, x2: 144px, y2: 94px, x3: 256px, y3: 94px, fill: #fbbf24)
]);
let rim = step(before: rim_scene, after: rim_scene, at: 0s);
let star = stack(children: [
triangle(x1: 200px, y1: 60px, x2: 150px, y2: 198px, x3: 250px, y3: 198px, fill: #ffffff),
triangle(x1: 200px, y1: 240px, x2: 150px, y2: 102px, x3: 250px, y3: 102px, fill: #ffffff)
]);
let out = tween(from: -34px, to: 34px, start: 0s, end: 1.5s);
let back = tween(from: 34px, to: -34px, start: 0s, end: 1.5s);
let drift = sequence(first: out, second: back, at: 1.5s);
let galaxy = translate(x: drift, y: 0px, scene: stack(children: [
rect(x: 110px, y: 40px, width: 240px, height: 220px, fill: #312e81),
ellipse(x: 150px, y: 92px, width: 130px, height: 130px, fill: #6d28d9),
ellipse(x: 188px, y: 122px, width: 64px, height: 64px, fill: #a855f7),
ellipse(x: 160px, y: 82px, width: 9px, height: 9px, fill: #fde047),
ellipse(x: 268px, y: 200px, width: 7px, height: 7px, fill: #fde047),
ellipse(x: 214px, y: 214px, width: 6px, height: 6px, fill: #f9a8d4)
]));
let peek = mask(alpha: star, content: galaxy);
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [base, rim, peek]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png16. Telescope Night Sky
Live canvas16. Telescope Night Sky
400 × 30060 fps
Loading renderer…
Rendered SVG16. Telescope Night Sky
Loading rendered frames…
anim
// Nested clips frame a telescope view panning across the night sky.
let scope_scene = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #050b14),
ellipse(x: 44px, y: 20px, width: 312px, height: 260px, fill: #111827),
rounded_rect(x: 72px, y: 58px, width: 256px, height: 184px, rx: 18px, ry: 18px, fill: #020617)
]);
let scope = step(before: scope_scene, after: scope_scene, at: 0s);
let out = tween(from: -70px, to: 70px, start: 0s, end: 1.5s);
let back = tween(from: 70px, to: -70px, start: 0s, end: 1.5s);
let pan = sequence(first: out, second: back, at: 1.5s);
let sky = translate(x: pan, y: 0px, scene: stack(children: [
rect(x: 40px, y: 58px, width: 340px, height: 184px, fill: #0b1026),
ellipse(x: 92px, y: 92px, width: 42px, height: 42px, fill: #38bdf8),
ellipse(x: 236px, y: 168px, width: 28px, height: 28px, fill: #f472b6),
ellipse(x: 296px, y: 88px, width: 22px, height: 22px, fill: #fde68a),
triangle(x1: 300px, y1: 88px, x2: 360px, y2: 76px, x3: 360px, y3: 102px, fill: #fef9c3),
ellipse(x: 140px, y: 200px, width: 6px, height: 6px, fill: #ffffff),
ellipse(x: 210px, y: 74px, width: 5px, height: 5px, fill: #ffffff)
]));
let outer = clip(x: 72px, y: 58px, width: 256px, height: 184px, scene: sky);
let focus = clip(x: 104px, y: 82px, width: 192px, height: 136px, scene: outer);
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [scope, focus]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png17. Steady Snail Crawl
Live canvas17. Steady Snail Crawl
400 × 30060 fps
Loading renderer…
Rendered SVG17. Steady Snail Crawl
Loading rendered frames…
anim
// A single linear tween carries a sleepy snail steadily across the leaf.
let route_scene = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #0b3b2e),
ellipse(x: 20px, y: 172px, width: 360px, height: 78px, fill: #166534),
rect(x: 44px, y: 208px, width: 312px, height: 4px, fill: #14532d)
]);
let route = step(before: route_scene, after: route_scene, at: 0s);
let crawl = tween(from: 60px, to: 340px, start: 0s, end: 3s);
let snail = translate(x: crawl, y: 196px, scene: stack(children: [
ellipse(x: -32px, y: -6px, width: 46px, height: 16px, fill: #a3e635),
ellipse(x: 8px, y: -24px, width: 20px, height: 26px, fill: #a3e635),
rect(x: 14px, y: -38px, width: 3px, height: 14px, fill: #a3e635),
rect(x: 23px, y: -38px, width: 3px, height: 14px, fill: #a3e635),
ellipse(x: 12px, y: -42px, width: 8px, height: 8px, fill: #1f2937),
ellipse(x: 21px, y: -42px, width: 8px, height: 8px, fill: #1f2937),
ellipse(x: -26px, y: -32px, width: 44px, height: 44px, fill: #f59e0b),
ellipse(x: -17px, y: -23px, width: 26px, height: 26px, fill: #fbbf24),
ellipse(x: -10px, y: -16px, width: 12px, height: 12px, fill: #f59e0b)
]));
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [route, snail]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png18. Springy Slime Bounce
Live canvas18. Springy Slime Bounce
400 × 30060 fps
Loading renderer…
Rendered SVG18. Springy Slime Bounce
Loading rendered frames…
anim
// Bézier spring easing makes a bouncy slime spring in with a satisfying overshoot.
let app_scene = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #12203a),
rect(x: 0px, y: 220px, width: 400px, height: 80px, fill: #1e3a5f),
ellipse(x: 150px, y: 232px, width: 100px, height: 20px, fill: #0f2a4a)
]);
let app = step(before: app_scene, after: app_scene, at: 0s);
let spring = cubic_bezier(x1: 0.18, y1: 0.9, x2: 0.24, y2: 1.0);
let drop_in = tween(from: -190px, to: 0px, start: 0s, end: 1s, easing: spring);
let fly_up = tween(from: 0px, to: -190px, start: 0s, end: 2s, easing: spring);
let offset = sequence(first: drop_in, second: fly_up, at: 1s);
let slime = translate(x: 200px, y: 200px + offset, scene: stack(children: [
ellipse(x: -48px, y: -46px, width: 96px, height: 86px, fill: #34d399),
ellipse(x: -48px, y: -14px, width: 96px, height: 44px, fill: #34d399),
ellipse(x: -22px, y: -24px, width: 16px, height: 20px, fill: #052e2b),
ellipse(x: 6px, y: -24px, width: 16px, height: 20px, fill: #052e2b),
ellipse(x: -19px, y: -20px, width: 6px, height: 6px, fill: #ffffff),
ellipse(x: 9px, y: -20px, width: 6px, height: 6px, fill: #ffffff),
ellipse(x: -9px, y: 2px, width: 18px, height: 10px, fill: #052e2b)
]));
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [app, slime]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png19. Three Growing Sprouts
Live canvas19. Three Growing Sprouts
400 × 30060 fps
Loading renderer…
Rendered SVG19. Three Growing Sprouts
Loading rendered frames…
anim
// One growth signal feeds three sprouts through simple arithmetic offsets.
let base_scene = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #bae6fd),
rect(x: 0px, y: 214px, width: 400px, height: 86px, fill: #7c4a26),
ellipse(x: 40px, y: 36px, width: 56px, height: 56px, fill: #fef9c3)
]);
let base = step(before: base_scene, after: base_scene, at: 0s);
let rise = tween(from: 0.18, to: 1.0, start: 0s, end: 1.5s);
let fall = tween(from: 1.0, to: 0.18, start: 0s, end: 1.5s);
let growth = sequence(first: rise, second: fall, at: 1.5s);
let sprout = stack(children: [
rect(x: -3px, y: -118px, width: 6px, height: 118px, fill: #16a34a),
ellipse(x: -28px, y: -104px, width: 28px, height: 16px, fill: #22c55e),
ellipse(x: 0px, y: -88px, width: 28px, height: 16px, fill: #22c55e),
ellipse(x: -15px, y: -134px, width: 30px, height: 30px, fill: #f472b6),
ellipse(x: -7px, y: -126px, width: 14px, height: 14px, fill: #fde047)
]);
let s1 = translate(x: 110px, y: 214px, scene: scale(x: 1.0, y: growth, scene: sprout));
let s2 = translate(x: 200px, y: 214px, scene: scale(x: 1.0, y: 0.25 + growth * 0.7, scene: sprout));
let s3 = translate(x: 290px, y: 214px, scene: scale(x: 1.0, y: 0.4 + growth * 0.45, scene: sprout));
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [base, s1, s2, s3]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png20. Egg Hatches into a Chick
Live canvas20. Egg Hatches into a Chick
400 × 30060 fps
Loading renderer…
Rendered SVG20. Egg Hatches into a Chick
Loading rendered frames…
anim
// A discrete step hatches a wobbling egg into a cheerful little chick.
let shell_scene = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #fde68a),
rect(x: 0px, y: 244px, width: 400px, height: 56px, fill: #f59e0b),
ellipse(x: 128px, y: 236px, width: 144px, height: 24px, fill: #d97706)
]);
let shell = step(before: shell_scene, after: shell_scene, at: 0s);
let egg = stack(children: [
ellipse(x: 160px, y: 108px, width: 80px, height: 128px, fill: #fffbeb),
ellipse(x: 176px, y: 150px, width: 14px, height: 14px, fill: #fcd34d),
ellipse(x: 208px, y: 180px, width: 11px, height: 11px, fill: #fcd34d),
ellipse(x: 188px, y: 130px, width: 9px, height: 9px, fill: #fde68a)
]);
let chick = stack(children: [
ellipse(x: 152px, y: 132px, width: 96px, height: 104px, fill: #fbbf24),
ellipse(x: 166px, y: 92px, width: 68px, height: 68px, fill: #fde047),
ellipse(x: 182px, y: 116px, width: 11px, height: 13px, fill: #1f2937),
ellipse(x: 206px, y: 116px, width: 11px, height: 13px, fill: #1f2937),
triangle(x1: 190px, y1: 128px, x2: 210px, y2: 128px, x3: 200px, y3: 142px, fill: #f97316),
triangle(x1: 166px, y1: 82px, x2: 180px, y2: 96px, x3: 194px, y3: 82px, fill: #fffbeb),
triangle(x1: 194px, y1: 82px, x2: 208px, y2: 96px, x3: 222px, y3: 82px, fill: #fffbeb),
ellipse(x: 168px, y: 232px, width: 26px, height: 12px, fill: #f97316),
ellipse(x: 206px, y: 232px, width: 26px, height: 12px, fill: #f97316)
]);
let status = step(before: egg, after: chick, at: 1.5s);
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [shell, status]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png21. Firework Fade
Live canvas21. Firework Fade
400 × 30060 fps
Loading renderer…
Rendered SVG21. Firework Fade
Loading rendered frames…
anim
// Opacity blooms a firework, then lets it gently fade into the night.
let sky_scene = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #0b1026),
ellipse(x: 60px, y: 60px, width: 5px, height: 5px, fill: #fef9c3),
ellipse(x: 340px, y: 90px, width: 4px, height: 4px, fill: #fef9c3),
ellipse(x: 300px, y: 250px, width: 4px, height: 4px, fill: #fef9c3),
ellipse(x: 90px, y: 240px, width: 4px, height: 4px, fill: #fef9c3)
]);
let sky = step(before: sky_scene, after: sky_scene, at: 0s);
let appear = tween(from: 0.0, to: 1.0, start: 0s, end: 1s);
let soften = tween(from: 1.0, to: 0.12, start: 0s, end: 2s);
let alpha = sequence(first: appear, second: soften, at: 1s);
let burst = tween(from: 0.35, to: 1.0, start: 0s, end: 0.7s, easing: cubic_bezier(x1: 0.1, y1: 0.8, x2: 0.2, y2: 1));
let firework = opacity(value: alpha, scene: translate(x: 200px, y: 132px, scene: scale(x: burst, y: burst, scene: stack(children: [
ellipse(x: 62px, y: -8px, width: 16px, height: 16px, fill: #f43f5e),
ellipse(x: 53px, y: -43px, width: 16px, height: 16px, fill: #fbbf24),
ellipse(x: 27px, y: -69px, width: 16px, height: 16px, fill: #38bdf8),
ellipse(x: -8px, y: -78px, width: 16px, height: 16px, fill: #34d399),
ellipse(x: -43px, y: -69px, width: 16px, height: 16px, fill: #a855f7),
ellipse(x: -69px, y: -43px, width: 16px, height: 16px, fill: #fb7185),
ellipse(x: -78px, y: -8px, width: 16px, height: 16px, fill: #f43f5e),
ellipse(x: -69px, y: 27px, width: 16px, height: 16px, fill: #fbbf24),
ellipse(x: -43px, y: 53px, width: 16px, height: 16px, fill: #38bdf8),
ellipse(x: -8px, y: 62px, width: 16px, height: 16px, fill: #34d399),
ellipse(x: 27px, y: 53px, width: 16px, height: 16px, fill: #a855f7),
ellipse(x: 53px, y: 27px, width: 16px, height: 16px, fill: #fb7185),
ellipse(x: -14px, y: -14px, width: 28px, height: 28px, fill: #fffbeb)
]))));
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [sky, firework]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png22. Kitten and Yarn Ball
Live canvas22. Kitten and Yarn Ball
400 × 30060 fps
Loading renderer…
Rendered SVG22. Kitten and Yarn Ball
Loading rendered frames…
anim
// A sequence bats a ball of yarn out, then rolls it back to the kitten.
let room_scene = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #fce7f3),
rect(x: 0px, y: 220px, width: 400px, height: 80px, fill: #f9a8d4),
ellipse(x: 92px, y: 214px, width: 34px, height: 12px, fill: #94a3b8),
ellipse(x: 40px, y: 176px, width: 66px, height: 54px, fill: #94a3b8),
ellipse(x: 30px, y: 148px, width: 54px, height: 50px, fill: #94a3b8),
triangle(x1: 34px, y1: 152px, x2: 30px, y2: 128px, x3: 50px, y3: 146px, fill: #94a3b8),
triangle(x1: 64px, y1: 146px, x2: 82px, y2: 128px, x3: 78px, y3: 152px, fill: #94a3b8),
ellipse(x: 42px, y: 166px, width: 9px, height: 11px, fill: #1f2937),
ellipse(x: 62px, y: 166px, width: 9px, height: 11px, fill: #1f2937),
ellipse(x: 52px, y: 178px, width: 8px, height: 5px, fill: #f472b6)
]);
let room = step(before: room_scene, after: room_scene, at: 0s);
let out = tween(from: 128px, to: 336px, start: 0s, end: 1.5s, easing: cubic_bezier(x1: 0.3, y1: 0, x2: 0.5, y2: 1));
let back = tween(from: 336px, to: 128px, start: 0s, end: 1.5s, easing: cubic_bezier(x1: 0.5, y1: 0, x2: 0.7, y2: 1));
let ball_x = sequence(first: out, second: back, at: 1.5s);
let linear_curve = cubic_bezier(x1: 0, y1: 0, x2: 1, y2: 1);
let roll = keyframes(frames: [
{time: 0s, value: 0deg, easing: linear_curve, hold: false},
{time: 3s, value: 720deg, easing: linear_curve, hold: false}
]);
let yarn = translate(x: ball_x, y: 202px, scene: rotate(angle: roll, scene: stack(children: [
ellipse(x: -20px, y: -20px, width: 40px, height: 40px, fill: #ef4444),
rect(x: -20px, y: -3px, width: 40px, height: 6px, fill: #fca5a5),
rect(x: -3px, y: -20px, width: 6px, height: 40px, fill: #fca5a5),
rect(x: -18px, y: -14px, width: 34px, height: 5px, fill: #fecaca)
])));
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [room, yarn]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png23. Pulsing Jellyfish
Live canvas23. Pulsing Jellyfish
400 × 30060 fps
Loading renderer…
Rendered SVG23. Pulsing Jellyfish
Loading rendered frames…
anim
// Repeat gives a deep-sea jellyfish its endless gentle pulse.
let sea_scene = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #042f2e),
rect(x: 0px, y: 54px, width: 400px, height: 26px, fill: #064e4a),
ellipse(x: 320px, y: 120px, width: 6px, height: 6px, fill: #99f6e4),
ellipse(x: 70px, y: 200px, width: 5px, height: 5px, fill: #99f6e4),
ellipse(x: 300px, y: 240px, width: 7px, height: 7px, fill: #99f6e4)
]);
let sea = step(before: sea_scene, after: sea_scene, at: 0s);
let expand = tween(from: 0.9, to: 1.14, start: 0s, end: 0.6s, easing: cubic_bezier(x1: 0.4, y1: 0, x2: 0.6, y2: 1));
let contract = tween(from: 1.14, to: 0.9, start: 0s, end: 0.6s, easing: cubic_bezier(x1: 0.4, y1: 0, x2: 0.6, y2: 1));
let pulse = repeat(signal: sequence(first: expand, second: contract, at: 0.6s), every: 1.2s);
let jelly = translate(x: 200px, y: 138px, scene: scale(x: pulse, y: pulse, scene: stack(children: [
ellipse(x: -60px, y: -58px, width: 120px, height: 96px, fill: #f472b6),
ellipse(x: -60px, y: -22px, width: 120px, height: 40px, fill: #f9a8d4),
ellipse(x: -32px, y: -44px, width: 14px, height: 18px, fill: #fce7f3),
ellipse(x: -20px, y: -30px, width: 11px, height: 13px, fill: #4a044e),
ellipse(x: 9px, y: -30px, width: 11px, height: 13px, fill: #4a044e),
ellipse(x: -8px, y: -12px, width: 16px, height: 8px, fill: #be185d),
rounded_rect(x: -46px, y: 12px, width: 8px, height: 60px, rx: 4px, ry: 4px, fill: #f9a8d4),
rounded_rect(x: -26px, y: 12px, width: 8px, height: 76px, rx: 4px, ry: 4px, fill: #f9a8d4),
rounded_rect(x: -6px, y: 12px, width: 8px, height: 64px, rx: 4px, ry: 4px, fill: #f9a8d4),
rounded_rect(x: 14px, y: 12px, width: 8px, height: 80px, rx: 4px, ry: 4px, fill: #f9a8d4),
rounded_rect(x: 34px, y: 12px, width: 8px, height: 62px, rx: 4px, ry: 4px, fill: #f9a8d4)
])));
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [sea, jelly]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png24. Ball Across the Toadstools
Live canvas24. Ball Across the Toadstools
400 × 30060 fps
Loading renderer…
Rendered SVG24. Ball Across the Toadstools
Loading rendered frames…
anim
// Three sequenced hops bounce a smiling ball across three toadstools.
let mushroom(cx) = stack(children: [
rect(x: cx - 9px, y: 196px, width: 18px, height: 42px, fill: #fef3c7),
ellipse(x: cx - 32px, y: 166px, width: 64px, height: 42px, fill: #ef4444),
ellipse(x: cx - 16px, y: 176px, width: 11px, height: 11px, fill: #fff1f2),
ellipse(x: cx + 6px, y: 182px, width: 9px, height: 9px, fill: #fff1f2)
]);
let base_scene = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #dcfce7),
rect(x: 0px, y: 234px, width: 400px, height: 66px, fill: #4ade80),
mushroom(cx: 90px),
mushroom(cx: 200px),
mushroom(cx: 310px)
]);
let base = step(before: base_scene, after: base_scene, at: 0s);
let hop1 = tween(from: 90px, to: 200px, start: 0s, end: 1s);
let hop2 = tween(from: 200px, to: 310px, start: 0s, end: 1s);
let hop3 = tween(from: 310px, to: 366px, start: 0s, end: 1s);
let path_x = sequence(first: sequence(first: hop1, second: hop2, at: 1s), second: hop3, at: 2s);
let arc_up = tween(from: 0px, to: -74px, start: 0s, end: 0.5s, easing: cubic_bezier(x1: 0.2, y1: 0.8, x2: 0.4, y2: 1));
let arc_down = tween(from: -74px, to: 0px, start: 0s, end: 0.5s, easing: cubic_bezier(x1: 0.6, y1: 0, x2: 0.8, y2: 1));
let arc = repeat(signal: sequence(first: arc_up, second: arc_down, at: 0.5s), every: 1s);
let ball = translate(x: path_x, y: 150px + arc, scene: stack(children: [
ellipse(x: -16px, y: -16px, width: 32px, height: 32px, fill: #38bdf8),
ellipse(x: -9px, y: -8px, width: 8px, height: 10px, fill: #0f172a),
ellipse(x: 1px, y: -8px, width: 8px, height: 10px, fill: #0f172a),
ellipse(x: -7px, y: 3px, width: 14px, height: 7px, fill: #0f172a)
]));
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [base, ball]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png25. Tulip Flowerbed
Live canvas25. Tulip Flowerbed
400 × 30060 fps
Loading renderer…
Rendered SVG25. Tulip Flowerbed
Loading rendered frames…
anim
// range and map plant a whole flowerbed of tulips that bloom together.
let base_scene = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #bae6fd),
rect(x: 0px, y: 214px, width: 400px, height: 86px, fill: #7c4a26),
ellipse(x: 328px, y: 30px, width: 54px, height: 54px, fill: #fef9c3)
]);
let base = step(before: base_scene, after: base_scene, at: 0s);
let rise = tween(from: 0.2, to: 1.0, start: 0s, end: 1.5s);
let settle = tween(from: 1.0, to: 0.2, start: 0s, end: 1.5s);
let bloom = sequence(first: rise, second: settle, at: 1.5s);
let indices = range(from: 0, to: 6);
let make_tulip(i) = translate(
x: 56px + i * 48px,
y: 214px,
scene: scale(
x: 1.0,
y: 0.3 + bloom * (0.7 + i * 0.05),
scene: stack(children: [
rect(x: -3px, y: -96px, width: 6px, height: 96px, fill: #16a34a),
ellipse(x: -20px, y: -82px, width: 22px, height: 12px, fill: #22c55e),
ellipse(x: -16px, y: -122px, width: 32px, height: 34px, fill: #ec4899),
rect(x: -16px, y: -116px, width: 32px, height: 14px, fill: #ec4899),
ellipse(x: -15px, y: -128px, width: 13px, height: 18px, fill: #f9a8d4),
ellipse(x: 3px, y: -128px, width: 13px, height: 18px, fill: #f9a8d4)
])
)
);
let tulips = map(items: indices, transform: make_tulip);
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [base, stack(children: tulips)]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png26. Rubber Duck Progress
Live canvas26. Rubber Duck Progress
400 × 30060 fps
Loading renderer…
Rendered SVG26. Rubber Duck Progress
Loading rendered frames…
anim
// A rising water fill and a floating rubber duck make a reversible progress bar.
let shell_scene = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #0b2a3a),
rounded_rect(x: 50px, y: 96px, width: 300px, height: 112px, rx: 24px, ry: 24px, fill: #cbd5e1),
rounded_rect(x: 70px, y: 150px, width: 260px, height: 44px, rx: 14px, ry: 14px, fill: #bfdbfe)
]);
let shell = step(before: shell_scene, after: shell_scene, at: 0s);
let fillup = tween(from: 0.05, to: 1.0, start: 0s, end: 2s);
let drain = tween(from: 1.0, to: 0.05, start: 0s, end: 1s);
let progress = sequence(first: fillup, second: drain, at: 2s);
let water = translate(x: 70px, y: 150px, scene: scale(x: progress, y: 1.0, scene: rounded_rect(x: 0px, y: 0px, width: 260px, height: 44px, rx: 14px, ry: 14px, fill: #38bdf8)));
let bob_up = tween(from: 0px, to: -6px, start: 0s, end: 0.4s);
let bob_down = tween(from: -6px, to: 0px, start: 0s, end: 0.4s);
let bob = repeat(signal: sequence(first: bob_up, second: bob_down, at: 0.4s), every: 0.8s);
let duck_out = tween(from: 88px, to: 322px, start: 0s, end: 2s);
let duck_back = tween(from: 322px, to: 88px, start: 0s, end: 1s);
let duck_x = sequence(first: duck_out, second: duck_back, at: 2s);
let duck = translate(x: duck_x, y: 142px + bob, scene: stack(children: [
ellipse(x: -17px, y: -14px, width: 36px, height: 28px, fill: #facc15),
ellipse(x: 4px, y: -28px, width: 22px, height: 22px, fill: #fde047),
triangle(x1: 22px, y1: -20px, x2: 38px, y2: -17px, x3: 22px, y3: -13px, fill: #f97316),
ellipse(x: 13px, y: -23px, width: 5px, height: 5px, fill: #1f2937)
]));
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [shell, water, duck]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png27. Day and Night Toggle
Live canvas27. Day and Night Toggle
400 × 30060 fps
Loading renderer…
Rendered SVG27. Day and Night Toggle
Loading rendered frames…
anim
// A day-night toggle slides a smiling sun across, waits, then rolls back to dawn.
let base_scene = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #0f172a),
rounded_rect(x: 98px, y: 118px, width: 204px, height: 84px, rx: 42px, ry: 42px, fill: #38bdf8),
ellipse(x: 128px, y: 150px, width: 30px, height: 16px, fill: #e0f2fe),
ellipse(x: 146px, y: 146px, width: 22px, height: 16px, fill: #e0f2fe),
ellipse(x: 262px, y: 142px, width: 5px, height: 5px, fill: #f8fafc),
ellipse(x: 278px, y: 168px, width: 4px, height: 4px, fill: #f8fafc)
]);
let base = step(before: base_scene, after: base_scene, at: 0s);
let on = tween(from: 150px, to: 250px, start: 0s, end: 0.7s, easing: cubic_bezier(x1: 0.2, y1: 0.8, x2: 0.3, y2: 1.0));
let off = tween(from: 250px, to: 150px, start: 0s, end: 1.3s);
let knob_x = sequence(first: on, second: off, at: 1.7s);
let knob = translate(x: knob_x, y: 160px, scene: stack(children: [
ellipse(x: -26px, y: -26px, width: 52px, height: 52px, fill: #fde047),
ellipse(x: -12px, y: -8px, width: 7px, height: 9px, fill: #92400e),
ellipse(x: 5px, y: -8px, width: 7px, height: 9px, fill: #92400e),
ellipse(x: -10px, y: 6px, width: 20px, height: 10px, fill: #92400e)
]));
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [base, knob]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png28. Flickering Campfire
Live canvas28. Flickering Campfire
400 × 30060 fps
Loading renderer…
Rendered SVG28. Flickering Campfire
Loading rendered frames…
anim
// Repeat makes three campfire flames flicker and dance into the night.
let flame(c) = stack(children: [
triangle(x1: 0px, y1: -62px, x2: -16px, y2: 2px, x3: 16px, y3: 2px, fill: c),
ellipse(x: -14px, y: -22px, width: 28px, height: 30px, fill: c)
]);
let scene_bg = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #0b1026),
ellipse(x: 70px, y: 60px, width: 5px, height: 5px, fill: #fef9c3),
ellipse(x: 320px, y: 90px, width: 4px, height: 4px, fill: #fef9c3),
ellipse(x: 130px, y: 48px, width: 4px, height: 4px, fill: #fef9c3),
ellipse(x: 120px, y: 244px, width: 160px, height: 26px, fill: #1c1917),
rounded_rect(x: 138px, y: 236px, width: 124px, height: 16px, rx: 8px, ry: 8px, fill: #78350f),
rounded_rect(x: 150px, y: 228px, width: 100px, height: 14px, rx: 7px, ry: 7px, fill: #92400e)
]);
let scene_base = step(before: scene_bg, after: scene_bg, at: 0s);
let up = tween(from: 0.25, to: 1.0, start: 0s, end: 0.4s, easing: cubic_bezier(x1: 0.4, y1: 0, x2: 0.6, y2: 1));
let down = tween(from: 1.0, to: 0.25, start: 0s, end: 0.4s, easing: cubic_bezier(x1: 0.4, y1: 0, x2: 0.6, y2: 1));
let beat = repeat(signal: sequence(first: up, second: down, at: 0.4s), every: 0.8s);
let f1 = translate(x: 178px, y: 236px, scene: scale(x: 1.0, y: beat, scene: flame(c: #ea580c)));
let f2 = translate(x: 200px, y: 236px, scene: scale(x: 1.0, y: 1.2 - beat * 0.5, scene: flame(c: #fb923c)));
let f3 = translate(x: 222px, y: 236px, scene: scale(x: 1.0, y: 0.4 + beat * 0.7, scene: flame(c: #fde047)));
export let main = composition(width: 400px, height: 300px, duration: 3s, fps: 60fps, scene: stack(children: [scene_base, f1, f2, f3]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.pngKnobs You Can Turn
33. Redecorate a Hot-Air Balloon
Everything this scene declares with param shows up as a control underneath the canvas. Drag the sliders, pick a new balloon colour, or fly it at night — the source never changes, only the values handed to it.
Live canvas33. Redecorate a Hot-Air Balloon
400 × 30060 fps
Loading renderer…
Rendered SVG33. Redecorate a Hot-Air Balloon
Loading rendered frames…
anim
// A hot-air balloon you can redecorate: every knob below is a public param.
param balloon_tint = { default: #f472b6, label: "Balloon" };
param basket_tint = { default: #b45309, label: "Basket" };
param puff = { default: 1.0, min: 0.6, max: 1.4, increment: 0.05, label: "Puffiness" };
param sway = { default: 9deg, min: 0deg, max: 24deg, label: "Sway" };
param sunny = { default: true, label: "Sunny day" };
let daytime = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #bae6fd),
ellipse(x: 300px, y: 34px, width: 56px, height: 56px, fill: #fde68a)
]);
let nighttime = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #4c1d95),
ellipse(x: 300px, y: 34px, width: 44px, height: 44px, fill: #e2e8f0)
]);
// A constant scene is lifted into a signal so it can sit beside the moving
// children in one list.
let weather = if sunny { daytime } else { nighttime };
let backdrop = step(before: weather, after: weather, at: 0s);
let cloud(offset) = translate(
x: offset,
y: 0px,
scene: stack(children: [
ellipse(x: 0px, y: 78px, width: 66px, height: 30px, fill: #ffffffcc),
ellipse(x: 26px, y: 66px, width: 52px, height: 40px, fill: #ffffffcc),
ellipse(x: 56px, y: 80px, width: 46px, height: 26px, fill: #ffffffcc)
])
);
let drift = tween(from: -120px, to: 460px, start: 0s, end: 6s);
let clouds = stack(children: [
translate(x: drift, y: 0px, scene: cloud(offset: 0px)),
translate(x: drift, y: 46px, scene: cloud(offset: -240px))
]);
let envelope = stack(children: [
ellipse(x: -46px, y: -52px, width: 92px, height: 104px, fill: balloon_tint),
ellipse(x: -28px, y: -44px, width: 24px, height: 78px, fill: #ffffff55),
rect(x: -14px, y: 44px, width: 28px, height: 10px, fill: balloon_tint)
]);
let basket = stack(children: [
rect(x: -3px, y: 52px, width: 2px, height: 18px, fill: #78350f),
rect(x: 1px, y: 52px, width: 2px, height: 18px, fill: #78350f),
rect(x: -13px, y: 68px, width: 26px, height: 20px, fill: basket_tint),
rect(x: -13px, y: 74px, width: 26px, height: 3px, fill: #78350f)
]);
let balloon = scale(x: puff, y: puff, scene: stack(children: [envelope, basket]));
// The balloon rocks between the two extremes of the declared sway angle.
let lean = tween(from: 0deg - sway, to: sway, start: 0s, end: 1.5s);
let unlean = tween(from: sway, to: 0deg - sway, start: 0s, end: 1.5s);
let rocking = repeat(signal: sequence(first: lean, second: unlean, at: 1.5s), every: 3s);
let rise = tween(from: 214px, to: 178px, start: 0s, end: 1.5s);
let fall = tween(from: 178px, to: 214px, start: 0s, end: 1.5s);
let bobbing = repeat(signal: sequence(first: rise, second: fall, at: 1.5s), every: 3s);
export let main = composition(
width: 400px,
height: 300px,
duration: 6s,
fps: 60fps,
scene: stack(children: [
backdrop,
clouds,
translate(x: 150px, y: bobbing, scene: rotate(angle: rocking, scene: balloon))
])
);TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.pngBorrowed From Better Artists
Nothing in this section was drawn by hand. Each piece is traced or transposed from a named source, so the composition is somebody else's and only the motion is ours.
34. Truchet Tiling
Live canvas34. Truchet Tiling
400 × 30060 fps
Loading renderer…
Rendered SVG34. Truchet Tiling
Loading rendered frames…
anim
// Sebastien Truchet, "Memoire sur les combinaisons" (1704): one half-square
// tile in four orientations. A diagonal wave flips each tile a quarter turn,
// so every frame is a valid Truchet tiling rather than a blur between two.
let half = triangle(x1: -20px, y1: -20px, x2: 20px, y2: -20px, x3: -20px, y3: 20px, fill: #f8fafc);
let flip(delay) = repeat(
signal: sequence(
first: step(before: 0deg, after: 90deg, at: delay),
second: step(before: 90deg, after: 180deg, at: delay),
at: 2s),
every: 4s);
let cell(i) = {
let row = floor(value: i / 10);
let col = i - row * 10;
translate(x: 20px + col * 40px, y: 20px + row * 40px,
scene: rotate(angle: (col + row) * 90deg + flip(delay: 0.1s * (col + row)),
scene: half))
};
let cells = map(items: range(from: 0, to: 80), transform: cell);
export let main = composition(
width: 400px, height: 320px, duration: 4s, fps: 60fps,
scene: stack(children: [
scene_signal(scene: rect(x: 0px, y: 0px, width: 400px, height: 320px, fill: #1e293b)),
stack(children: cells)
]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.png35. Oswald the Lucky Rabbit Takes a Jump
The figure is traced straight out of a 1928 public-domain drawing by scripts/svg_to_anim.py; every anchor and tangent is the original artist's. Because the pose is already mid-leap, the animation only adds what the drawing implies: anticipate, launch, hang, land, settle.
Live canvas35. Oswald the Lucky Rabbit Takes a Jump
400 × 30060 fps
Loading renderer…
Rendered SVG35. Oswald the Lucky Rabbit Takes a Jump
Loading rendered frames…
anim
// Oswald the Lucky Rabbit (1928, public domain), traced from the source SVG by
// scripts/svg_to_anim.py. Every anchor below is the original artist's; the
// animation only adds what the drawing already implies -- he is mid-jump, so
// he gets a jump: anticipate, launch, hang, land, recover.
// Traced from the source SVG by scripts/svg_to_anim.py.
// Every anchor and tangent below comes from the original file.
let oswald_part_00 = fill_path(
path: bezier_path(contours: [
{
closed: true,
points: [
{x: -25.19px, y: -95.02px, in_x: 0px, in_y: 0px, out_x: -2.94px, out_y: -0.06px},
{x: -26.99px, y: -81.78px, in_x: -2.35px, in_y: -7.08px, out_x: 0.81px, out_y: 2.44px},
{x: -25.63px, y: -75.55px, in_x: 1.37px, in_y: -0.9px, out_x: -1.33px, out_y: 0.87px},
{x: -30.33px, y: -81.35px, in_x: 2.32px, in_y: 3.2px, out_x: -4.72px, out_y: -6.5px},
{x: -40.95px, y: -86.74px, in_x: 2.91px, in_y: -2.63px, out_x: -0.97px, out_y: 0.88px},
{x: -42.28px, y: -83.81px, in_x: 0.02px, in_y: -1.2px, out_x: -0.02px, out_y: 1.8px},
{x: -38.22px, y: -77.71px, in_x: -2.47px, in_y: -2.81px, out_x: 3.46px, out_y: 3.94px},
{x: -33.55px, y: -70.77px, in_x: 0.54px, in_y: -0.62px, out_x: -0.76px, out_y: 0.88px},
{x: -36.59px, y: -71.38px, in_x: 1.24px, in_y: 0.47px, out_x: -7.64px, out_y: -2.88px},
{x: -48.94px, y: -70.77px, in_x: 1.26px, in_y: -2.72px, out_x: -1.24px, out_y: 2.69px},
{x: -42.09px, y: -64.25px, in_x: -5.73px, in_y: -1.66px, out_x: 2.63px, out_y: 0.77px},
{x: -37.26px, y: -62.34px, in_x: 0.29px, in_y: -0.46px, out_x: -0.29px, out_y: 0.46px},
{x: -39.25px, y: -61.22px, in_x: 1.05px, in_y: 0.09px, out_x: -1.09px, out_y: -0.1px},
{x: -46.32px, y: -56.21px, in_x: 0.89px, in_y: -2.33px, out_x: -1.3px, out_y: 3.42px},
{x: -45.86px, y: -48.08px, in_x: -1.52px, in_y: -0.58px, out_x: 0.75px, out_y: 0.29px},
{x: -40.85px, y: -50.49px, in_x: -2.07px, in_y: 1.64px, out_x: 1.49px, out_y: -0.93px},
{x: -36.84px, y: -53.4px, in_x: -1.03px, in_y: 0.47px, out_x: 0.47px, out_y: -0.21px},
{x: -33.03px, y: -48.52px, in_x: -0.73px, in_y: -1.11px, out_x: 1.13px, out_y: 1.72px},
{x: -30.62px, y: -42.2px, in_x: -0.61px, in_y: -2.18px, out_x: 4.47px, out_y: 14.94px},
{x: -23.26px, y: -17.69px, in_x: -2.18px, in_y: -5.94px, out_x: 2.34px, out_y: 6.37px},
{x: -11.98px, y: 6.29px, in_x: -1.99px, in_y: -2.84px, out_x: 0.94px, out_y: 1.34px},
{x: -15.98px, y: 13.02px, in_x: 4.39px, in_y: -4.45px, out_x: -6.11px, out_y: 6.2px},
{x: -27.11px, y: 35.27px, in_x: 0.81px, in_y: -7.63px, out_x: -0.31px, out_y: 2.94px},
{x: -27.85px, y: 40.83px, in_x: 0.1px, in_y: -0.12px, out_x: -0.1px, out_y: 0.12px},
{x: -32.24px, y: 35.31px, in_x: 2.32px, in_y: 3.15px, out_x: -8.15px, out_y: -11.1px},
{x: -49.14px, y: 27.33px, in_x: 4.72px, in_y: -5.02px, out_x: -1.94px, out_y: 2.07px},
{x: -51.23px, y: 40.13px, in_x: 0px, in_y: -9.84px, out_x: 0px, out_y: 6.69px},
{x: -51.24px, y: 50.83px, in_x: 0.92px, in_y: -0.63px, out_x: -0.92px, out_y: 0.64px},
{x: -55.23px, y: 46.79px, in_x: 1.21px, in_y: 1.78px, out_x: -2.64px, out_y: -3.87px},
{x: -64.94px, y: 37.38px, in_x: 2.14px, in_y: 0.77px, out_x: -2.31px, out_y: -0.83px},
{x: -70.59px, y: 40.93px, in_x: 2.15px, in_y: -3.62px, out_x: -4.45px, out_y: 7.48px},
{x: -68.9px, y: 59.83px, in_x: -5.65px, in_y: -5.94px, out_x: 4.93px, out_y: 5.18px},
{x: -55.04px, y: 77.89px, in_x: -5.62px, in_y: -8.57px, out_x: 6.23px, out_y: 9.5px},
{x: -38.48px, y: 93.98px, in_x: -3.52px, in_y: 0.03px, out_x: 1.38px, out_y: -0.01px},
{x: -33.73px, y: 92.24px, in_x: -1.23px, in_y: 0.95px, out_x: 2.17px, out_y: -1.67px},
{x: -31.02px, y: 80.02px, in_x: -0.05px, in_y: 8.28px, out_x: 0.03px, out_y: -5.83px},
{x: -32.3px, y: 64.43px, in_x: 0.45px, in_y: 2.69px, out_x: -0.27px, out_y: -1.63px},
{x: -33.12px, y: 59.54px, in_x: -0.58px, in_y: 0.55px, out_x: 0.46px, out_y: -0.43px},
{x: -29.48px, y: 62.41px, in_x: -1.51px, in_y: -1.2px, out_x: 2px, out_y: 1.58px},
{x: -24.45px, y: 65.29px, in_x: -0.77px, in_y: 0px, out_x: 0.77px, out_y: 0px},
{x: -19.2px, y: 67.83px, in_x: -2.12px, in_y: -1.4px, out_x: 10.07px, out_y: 6.62px},
{x: 11.35px, y: 69.35px, in_x: -12.91px, in_y: 5.47px, out_x: 0.8px, out_y: -0.46px},
{x: 13.55px, y: 68.15px, in_x: -0.7px, in_y: 0.37px, out_x: 0.27px, out_y: 0.53px},
{x: 13.9px, y: 69.92px, in_x: 0.11px, in_y: -0.7px, out_x: -0.28px, out_y: 1.81px},
{x: 9.76px, y: 78.02px, in_x: 1.82px, in_y: -4.63px, out_x: -1.46px, out_y: 3.72px},
{x: 8.35px, y: 86.02px, in_x: -0.69px, in_y: -3.48px, out_x: 0.69px, out_y: 3.48px},
{x: 16.8px, y: 93.95px, in_x: -4.39px, in_y: -0.71px, out_x: 4.39px, out_y: 0.71px},
{x: 33.39px, y: 87.17px, in_x: -6.62px, in_y: 5.95px, out_x: 5.71px, out_y: -5.13px},
{x: 48.03px, y: 66.69px, in_x: -5.09px, in_y: 9.97px, out_x: 6.63px, out_y: -12.97px},
{x: 50.8px, y: 44.13px, in_x: 4.66px, in_y: 3.05px, out_x: -2.47px, out_y: -1.62px},
{x: 42.29px, y: 45.17px, in_x: 2.39px, in_y: -2.16px, out_x: -0.39px, out_y: 0.35px},
{x: 40.41px, y: 46.68px, in_x: 0.71px, in_y: 0.03px, out_x: -0.46px, out_y: -0.02px},
{x: 40.84px, y: 40.59px, in_x: -0.31px, in_y: 3.91px, out_x: 0.29px, out_y: -2.72px},
{x: 37.43px, y: 30.34px, in_x: 4.66px, in_y: 2.15px, out_x: -2.88px, out_y: -1.69px},
{x: 28.78px, y: 31.85px, in_x: 2.78px, in_y: -2.15px, out_x: -1.28px, out_y: -4.77px},
{x: 22.94px, y: 20.9px, in_x: 0.31px, in_y: 0.94px, out_x: -0.45px, out_y: -1.37px},
{x: 29.8px, y: 5.58px, in_x: -2px, in_y: 4.92px, out_x: 2.62px, out_y: -6.43px},
{x: 50px, y: -36.31px, in_x: -0.81px, in_y: 2.38px, out_x: 0.88px, out_y: -2.57px},
{x: 52.14px, y: -35.46px, in_x: 0.52px, in_y: -2.71px, out_x: -1.15px, out_y: 6.01px},
{x: 58.66px, y: -31.34px, in_x: -3.54px, in_y: 4.5px, out_x: 0.91px, out_y: -1.16px},
{x: 60.17px, y: -34.76px, in_x: -0.11px, in_y: 1.49px, out_x: 0.06px, out_y: -0.86px},
{x: 59.98px, y: -39.28px, in_x: 0.35px, in_y: 2.02px, out_x: -0.3px, out_y: -1.78px},
{x: 58.97px, y: -44.01px, in_x: -0.09px, in_y: 1.32px, out_x: 0.1px, out_y: -1.52px},
{x: 63.95px, y: -45.41px, in_x: -1.65px, in_y: 0.5px, out_x: 3.28px, out_y: -0.98px},
{x: 72.1px, y: -50.59px, in_x: -1.59px, in_y: 2.15px, out_x: 3.67px, out_y: -4.97px},
{x: 64.46px, y: -54.51px, in_x: 8.42px, in_y: -2.53px, out_x: -2.4px, out_y: 0.72px},
{x: 59.88px, y: -53.41px, in_x: 0.65px, in_y: 0.87px, out_x: -0.63px, out_y: -0.84px},
{x: 64.1px, y: -58.84px, in_x: -2.44px, in_y: 2.86px, out_x: 4.67px, out_y: -5.47px},
{x: 68.7px, y: -69.47px, in_x: 1.61px, in_y: 1.61px, out_x: -1.47px, out_y: -1.47px},
{x: 59.85px, y: -65.11px, in_x: 2.69px, in_y: -3.52px, out_x: -2.47px, out_y: 3.23px},
{x: 54.3px, y: -63.31px, in_x: 1.59px, in_y: 1.92px, out_x: -0.77px, out_y: -0.92px},
{x: 55.97px, y: -69.36px, in_x: -2.04px, in_y: 3.7px, out_x: 1.47px, out_y: -2.67px},
{x: 58.65px, y: -77.13px, in_x: -0.01px, in_y: 1.6px, out_x: 0.01px, out_y: -2.61px},
{x: 56.13px, y: -80.04px, in_x: 2.27px, in_y: 0px, out_x: -1.47px, out_y: 0px},
{x: 51.7px, y: -78.02px, in_x: 1.1px, in_y: -1.17px, out_x: -2.19px, out_y: 2.33px},
{x: 46.13px, y: -66.36px, in_x: 0.7px, in_y: -2.2px, out_x: -0.51px, out_y: 1.58px},
{x: 41.45px, y: -62.73px, in_x: 1.61px, in_y: -1.8px, out_x: -1.32px, out_y: 1.48px},
{x: 36.54px, y: -59.41px, in_x: 2.24px, in_y: 0px, out_x: -2.26px, out_y: 0px},
{x: 29.53px, y: -55.52px, in_x: 3.1px, in_y: -2.97px, out_x: -3.82px, out_y: 3.66px},
{x: 26.49px, y: -47.48px, in_x: -1.91px, in_y: -1.18px, out_x: 2.33px, out_y: 1.44px},
{x: 34.47px, y: -48.04px, in_x: -1.84px, in_y: 1.71px, out_x: 2.14px, out_y: -1.98px},
{x: 37.44px, y: -48.99px, in_x: -0.53px, in_y: -0.44px, out_x: 1.26px, out_y: 1.05px},
{x: 37.71px, y: -43.67px, in_x: 0.4px, in_y: -1.79px, out_x: -1.11px, out_y: 4.93px},
{x: 30.16px, y: -24.75px, in_x: 1.41px, in_y: -2.8px, out_x: -0.91px, out_y: 1.8px},
{x: 27.48px, y: -19.48px, in_x: 0.7px, in_y: 0.11px, out_x: -0.85px, out_y: -0.13px},
{x: 26.35px, y: -25.2px, in_x: 0.58px, in_y: 2.77px, out_x: -0.46px, out_y: -2.19px},
{x: 24.02px, y: -31.27px, in_x: 0.92px, in_y: 1.32px, out_x: -2.35px, out_y: -3.34px},
{x: 19.72px, y: -38.04px, in_x: 0.2px, in_y: 1.83px, out_x: -0.23px, out_y: -2.05px},
{x: 23.31px, y: -48.04px, in_x: -2.24px, in_y: 5.62px, out_x: 2.12px, out_y: -5.32px},
{x: 28.54px, y: -62.44px, in_x: -0.76px, in_y: 2.59px, out_x: 1.04px, out_y: -3.53px},
{x: 31.98px, y: -74.49px, in_x: -0.88px, in_y: 4.03px, out_x: 0.86px, out_y: -3.93px},
{x: 29.49px, y: -87.55px, in_x: 3.57px, in_y: 2.35px, out_x: -2.73px, out_y: -1.8px},
{x: 20.12px, y: -85.15px, in_x: 2.37px, in_y: -3.3px, out_x: -1.49px, out_y: 2.08px},
{x: 14.82px, y: -74.21px, in_x: 1.08px, in_y: -3.47px, out_x: -1.64px, out_y: 5.28px},
{x: 11.07px, y: -57.87px, in_x: 1.17px, in_y: -5.43px, out_x: -0.78px, out_y: 3.6px},
{x: 8.78px, y: -46.51px, in_x: 0.32px, in_y: -2.69px, out_x: -0.46px, out_y: 3.94px},
{x: 8.07px, y: -40.59px, in_x: 0.61px, in_y: -0.11px, out_x: -1.04px, out_y: 0.19px},
{x: 4.27px, y: -40.84px, in_x: 0.64px, in_y: 0.42px, out_x: -0.7px, out_y: -0.45px},
{x: 5.86px, y: -47.74px, in_x: -0.99px, in_y: 3.68px, out_x: 2.42px, out_y: -9.03px},
{x: 9.69px, y: -73.7px, in_x: -0.25px, in_y: 9.06px, out_x: 0.22px, out_y: -7.79px},
{x: 6.39px, y: -89.28px, in_x: 2.76px, in_y: 4.21px, out_x: -2.61px, out_y: -3.99px},
{x: -3.81px, y: -86.97px, in_x: 2.68px, in_y: -5.19px, out_x: -1.03px, out_y: 1.98px},
{x: -5.51px, y: -76.32px, in_x: 0px, in_y: -6.35px, out_x: -0px, out_y: 4.44px},
{x: -4.15px, y: -56.12px, in_x: -0.42px, in_y: -9.63px, out_x: 0.45px, out_y: 10.38px},
{x: -3.93px, y: -39.22px, in_x: 0.55px, in_y: -0.86px, out_x: -0.67px, out_y: 1.06px},
{x: -8.01px, y: -34.79px, in_x: 2.07px, in_y: -2.25px, out_x: -4.64px, out_y: 5.05px},
{x: -14.45px, y: -41.3px, in_x: 2.51px, in_y: 12.28px, out_x: -1.02px, out_y: -5px},
{x: -16.16px, y: -53.64px, in_x: 0.23px, in_y: 3.39px, out_x: -0.12px, out_y: -1.81px},
{x: -15.48px, y: -57.75px, in_x: -0.52px, in_y: 1.13px, out_x: 1.18px, out_y: -2.59px},
{x: -11.88px, y: -58.96px, in_x: -0.75px, in_y: -1.96px, out_x: 0.75px, out_y: 1.96px},
{x: -7.58px, y: -59.27px, in_x: -1.48px, in_y: 2.04px, out_x: 1.62px, out_y: -2.23px},
{x: -8.98px, y: -71.9px, in_x: 2.42px, in_y: 2.76px, out_x: -0.88px, out_y: -1px},
{x: -12.6px, y: -74.4px, in_x: 1.52px, in_y: 0.39px, out_x: -1.09px, out_y: -0.28px},
{x: -16.29px, y: -74.92px, in_x: 0.49px, in_y: 0.58px, out_x: -0.65px, out_y: -0.78px},
{x: -17.22px, y: -80.55px, in_x: 0.51px, in_y: 2.79px, out_x: -1.22px, out_y: -6.63px},
{x: -22.9px, y: -93.91px, in_x: 2.56px, in_y: 2.28px, out_x: -0.84px, out_y: -0.75px},
{x: -25.19px, y: -95.02px, in_x: 0.68px, in_y: 0.01px, out_x: 0px, out_y: 0px},
],
},
]),
fill: #000000,
even_odd: false,
);
let oswald_part_01 = fill_path(
path: bezier_path(contours: [
{
closed: true,
points: [
{x: 7.8px, y: 9.91px, in_x: 0px, in_y: 0px, out_x: 9.47px, out_y: -3.8px},
{x: 24.23px, y: -21.56px, in_x: 5.3px, in_y: 10.47px, out_x: -0.97px, out_y: -1.92px},
{x: 18.42px, y: -19.49px, in_x: 2.86px, in_y: -3.25px, out_x: -3.62px, out_y: 4.12px},
{x: 15.26px, y: -19.93px, in_x: -1.52px, in_y: 4.42px, out_x: 1.87px, out_y: -5.43px},
{x: 15.43px, y: -35.74px, in_x: 1.79px, in_y: 1.79px, out_x: -3.46px, out_y: -3.46px},
{x: 2.86px, y: -29.18px, in_x: 2.35px, in_y: -6.49px, out_x: -1.34px, out_y: 3.72px},
{x: 0.01px, y: -29.04px, in_x: 0.72px, in_y: 3.62px, out_x: -1.17px, out_y: -5.83px},
{x: -8.33px, y: -31.64px, in_x: 4.48px, in_y: -4.08px, out_x: -3.57px, out_y: 3.25px},
{x: -15.15px, y: -9.17px, in_x: 0.02px, in_y: -8.55px, out_x: -0.02px, out_y: 8.63px},
{x: -5.75px, y: 7.31px, in_x: -5.71px, in_y: -1.36px, out_x: 1.73px, out_y: 0.41px},
{x: -2.52px, y: 6.43px, in_x: -0.58px, in_y: 1.04px, out_x: 1.37px, out_y: -2.45px},
{x: 2.15px, y: 8.84px, in_x: -0.46px, in_y: -3.12px, out_x: 0.53px, out_y: 3.55px},
{x: 7.8px, y: 9.91px, in_x: -2.51px, in_y: 1.01px, out_x: 0px, out_y: 0px},
],
},
]),
fill: #ffffff,
even_odd: false,
);
let oswald_part_02 = fill_path(
path: bezier_path(contours: [
{
closed: true,
points: [
{x: -2.33px, y: 14.21px, in_x: 0px, in_y: 0px, out_x: 0px, out_y: -4.38px},
{x: -4.47px, y: 12.49px, in_x: 0.75px, in_y: -3.77px, out_x: -0.84px, out_y: 4.22px},
{x: -3.68px, y: 17.75px, in_x: -1.47px, in_y: 0px, out_x: 0.97px, out_y: 0px},
{x: -2.33px, y: 14.21px, in_x: 0px, in_y: 2.54px, out_x: 0px, out_y: 0px},
],
},
]),
fill: #ffffff,
even_odd: false,
);
let oswald_part_03 = fill_path(
path: bezier_path(contours: [
{
closed: true,
points: [
{x: -1.65px, y: 23.94px, in_x: 0px, in_y: 0px, out_x: -6.4px, out_y: -0.02px},
{x: -19.31px, y: 27.92px, in_x: 4.94px, in_y: -2.8px, out_x: -2.2px, out_y: 1.25px},
{x: -23.85px, y: 31.46px, in_x: 1px, in_y: -1.58px, out_x: -0.7px, out_y: 1.1px},
{x: -25.17px, y: 38.61px, in_x: 0.2px, in_y: -2.93px, out_x: -0.51px, out_y: 7.43px},
{x: -27.49px, y: 45.09px, in_x: 2.06px, in_y: 1.13px, out_x: -1.32px, out_y: -0.72px},
{x: -28.59px, y: 50.23px, in_x: -0.44px, in_y: -5.1px, out_x: 0.59px, out_y: 6.79px},
{x: -23.48px, y: 62.12px, in_x: -3.09px, in_y: -1.17px, out_x: 1.27px, out_y: 0.48px},
{x: -17.51px, y: 66.14px, in_x: -2.25px, in_y: -1.42px, out_x: 2.22px, out_y: 1.4px},
{x: -10.89px, y: 69.72px, in_x: -1.42px, in_y: -0.57px, out_x: 4.35px, out_y: 1.85px},
{x: 5.33px, y: 69.28px, in_x: -5.2px, in_y: 2.01px, out_x: 2.03px, out_y: -0.78px},
{x: 12.5px, y: 66.3px, in_x: -2.38px, in_y: 1.27px, out_x: -0.08px, out_y: -0.18px},
{x: 12.28px, y: 65.74px, in_x: 0.06px, in_y: 0.2px, out_x: -3.48px, out_y: -11.14px},
{x: 19.3px, y: 42.91px, in_x: -3.5px, in_y: 5.11px, out_x: 1.51px, out_y: -2.06px},
{x: 25.53px, y: 34.9px, in_x: -2.53px, in_y: 2.76px, out_x: -2.04px, out_y: -2.62px},
{x: 17.31px, y: 27.57px, in_x: 2.85px, in_y: 1.46px, out_x: -1.78px, out_y: -0.91px},
{x: 7px, y: 24.7px, in_x: 3.9px, in_y: 0.67px, out_x: -2.82px, out_y: -0.48px},
{x: -1.65px, y: 23.94px, in_x: 2.91px, in_y: 0.01px, out_x: 0px, out_y: 0px},
],
},
]),
fill: #ffffff,
even_odd: false,
);
let oswald_part_04 = fill_path(
path: bezier_path(contours: [
{
closed: true,
points: [
{x: -9.37px, y: -13.56px, in_x: 0px, in_y: 0px, out_x: 0.66px, out_y: -4.96px},
{x: -5.11px, y: -20.44px, in_x: -1.75px, in_y: -1.08px, out_x: 1.35px, out_y: 0.83px},
{x: -5.21px, y: -6.66px, in_x: 1.36px, in_y: -1.36px, out_x: -1.59px, out_y: 1.59px},
{x: -9.24px, y: -7.48px, in_x: 0.27px, in_y: 1.33px, out_x: -0.27px, out_y: -1.33px},
{x: -9.37px, y: -13.56px, in_x: -0.35px, in_y: 2.66px, out_x: 0px, out_y: 0px},
],
},
]),
fill: #000000,
even_odd: false,
);
let oswald_part_05 = fill_path(
path: bezier_path(contours: [
{
closed: true,
points: [
{x: 4.58px, y: -19.13px, in_x: 0px, in_y: 0px, out_x: 1.6px, out_y: -1.6px},
{x: 7.95px, y: -14.36px, in_x: 0.04px, in_y: -3.81px, out_x: -0.09px, out_y: 8.86px},
{x: 3.4px, y: -4.95px, in_x: 1.39px, in_y: 3.66px, out_x: -1.39px, out_y: -3.66px},
{x: 4.58px, y: -19.13px, in_x: -1.25px, in_y: 1.25px, out_x: 0px, out_y: 0px},
],
},
]),
fill: #000000,
even_odd: false,
);
let oswald_part_06 = fill_path(
path: bezier_path(contours: [
{
closed: true,
points: [
{x: 13.59px, y: -1.87px, in_x: 0px, in_y: 0px, out_x: 0.96px, out_y: -1.45px},
{x: 15.62px, y: -6.63px, in_x: -0.14px, in_y: 1.16px, out_x: 0.34px, out_y: -2.75px},
{x: 17.52px, y: -10.44px, in_x: -0.97px, in_y: -0.6px, out_x: 1.19px, out_y: 0.74px},
{x: 15.42px, y: -0.42px, in_x: 2.11px, in_y: -3.39px, out_x: -1.24px, out_y: 1.99px},
{x: 13.03px, y: 1.97px, in_x: 0.73px, in_y: 0.39px, out_x: -0.8px, out_y: -0.43px},
{x: 13.59px, y: -1.87px, in_x: -0.96px, in_y: 1.45px, out_x: 0px, out_y: 0px},
],
},
]),
fill: #000000,
even_odd: false,
);
let oswald = stack(children: [
oswald_part_00,
oswald_part_01,
oswald_part_02,
oswald_part_03,
oswald_part_04,
oswald_part_05,
oswald_part_06,
]);
let ease_out = cubic_bezier(x1: 0.16, y1: 0.84, x2: 0.3, y2: 1);
let ease_in = cubic_bezier(x1: 0.7, y1: 0, x2: 0.84, y2: 0.16);
// One 2.4s beat: crouch, launch, hang, land, settle.
let lift = repeat(signal: sequence(
first: sequence(
first: tween(from: 0px, to: 14px, start: 0s, end: 0.45s, easing: ease_out),
second: tween(from: 14px, to: -62px, start: 0s, end: 0.5s, easing: ease_out),
at: 0.45s),
second: sequence(
first: tween(from: -62px, to: 16px, start: 0s, end: 0.55s, easing: ease_in),
second: tween(from: 16px, to: 0px, start: 0s, end: 0.9s, easing: ease_out),
at: 0.55s),
at: 0.95s), every: 2.4s);
let squash = repeat(signal: sequence(
first: sequence(
first: tween(from: 1.0, to: 0.84, start: 0s, end: 0.45s, easing: ease_out),
second: tween(from: 0.84, to: 1.14, start: 0s, end: 0.5s, easing: ease_out),
at: 0.45s),
second: sequence(
first: tween(from: 1.14, to: 0.82, start: 0s, end: 0.55s, easing: ease_in),
second: tween(from: 0.82, to: 1.0, start: 0s, end: 0.9s, easing: ease_out),
at: 0.55s),
at: 0.95s), every: 2.4s);
// Volume is conserved: what he loses in height he gains in width.
let stretch = repeat(signal: sequence(
first: sequence(
first: tween(from: 1.0, to: 1.12, start: 0s, end: 0.45s, easing: ease_out),
second: tween(from: 1.12, to: 0.9, start: 0s, end: 0.5s, easing: ease_out),
at: 0.45s),
second: sequence(
first: tween(from: 0.9, to: 1.14, start: 0s, end: 0.55s, easing: ease_in),
second: tween(from: 1.14, to: 1.0, start: 0s, end: 0.9s, easing: ease_out),
at: 0.55s),
at: 0.95s), every: 2.4s);
let shade = repeat(signal: sequence(
first: sequence(
first: tween(from: 1.0, to: 1.06, start: 0s, end: 0.45s, easing: ease_out),
second: tween(from: 1.06, to: 0.44, start: 0s, end: 0.5s, easing: ease_out),
at: 0.45s),
second: sequence(
first: tween(from: 0.44, to: 1.08, start: 0s, end: 0.55s, easing: ease_in),
second: tween(from: 1.08, to: 1.0, start: 0s, end: 0.9s, easing: ease_out),
at: 0.55s),
at: 0.95s), every: 2.4s);
let backdrop = stack(children: [
rect(x: 0px, y: 0px, width: 400px, height: 300px, fill: #efe9d8),
rect(x: 0px, y: 246px, width: 400px, height: 54px, fill: #ded5bd)
]);
export let main = composition(
width: 400px, height: 300px, duration: 4.8s, fps: 60fps,
scene: stack(children: [
scene_signal(scene: backdrop),
translate(x: 200px, y: 250px,
scene: scale(x: shade, y: shade,
scene: scene_signal(scene: ellipse(x: -52px, y: -8px, width: 104px, height: 16px, fill: #cfc4a6)))),
translate(x: 200px, y: 170px + lift,
scene: scale(x: stretch, y: squash, scene: scene_signal(scene: oswald)))
]));TerminalAfter saving the source as example.anim
anim render example.anim --range 0..120 -o frame_%04d.pngPhysics & Showcase
29. 2D Skeletal Physics Bounding Creature
Rendered SVG29. 2D Skeletal Physics Bounding Creature
Loading rendered frames…
30. Pure Functional Rubik's Cube Superflip Solver
Rendered SVG30. Pure Functional Rubik's Cube Superflip Solver
Loading rendered frames…
31. Rubber Hose Web Acrobat Reel
Rendered SVG31. Rubber Hose Web Acrobat Reel
Loading rendered frames…
32. Bézier Caterpillar Motion Reel
Rendered SVG32. Bézier Caterpillar Motion Reel
Loading rendered frames…