From rvanbaalen
Generates professional Lottie animations from static SVGs. Replaces After Effects for motion graphics. Use when the user asks to: animate logo, create lottie, svg animation, motion graphics, wiggle animation, bounce effect, rotate animation, pulse effect, entrance animation, loading animation, loop animation, icon animation, character animation, morphing, path drawing, trim path, walking animation, run cycle, walk cycle, frame-by-frame animation, sprite animation. Supports advanced bezier curves, shape modifiers, parenting, mattes, morphing, character rigs, and professional frame-by-frame animation techniques.
How this skill is triggered — by the user, by Claude, or both
Slash command
/rvanbaalen:lottie-animatorThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Professional skill to create advanced Lottie animations from SVGs, eliminating the need for After Effects.
Professional skill to create advanced Lottie animations from SVGs, eliminating the need for After Effects.
Activate this skill when the user requests:
Before animating ANY SVG, you MUST understand its path structure.
See: references/svg-path-mastery.md
| Command | Description | Lottie Conversion |
|---|---|---|
| M x,y | Move to | Starting vertex |
| L x,y | Line to | Vertex with zero tangents |
| C cp1 cp2 end | Cubic bezier | Native support |
| Q ctrl end | Quadratic bezier | Convert to cubic |
| A rx ry ... | Arc | Split into cubic segments |
| Z | Close path | Set c: true |
For C x1,y1 x2,y2 x,y from point (px, py):
- Previous vertex outTangent: [x1-px, y1-py]
- Current vertex: [x, y]
- Current vertex inTangent: [x2-x, y2-y]
MANDATORY before any code. Define:
Example: "Fintech Logo → professional + trust → precise and controlled movement"
Example: "Music App → creative + energy → organic with rhythmic pulses"
Example: "Healthcare → calm + reliable → smooth, slow easings"
Before animating, thoroughly analyze:
# Analyze SVG structure
cat icon.svg | grep -E '<(path|g|rect|circle|ellipse|line|polyline)' | head -30
Key Questions:
| Strategy | Best For | Technique |
|---|---|---|
| Draw On | Stroke icons, signatures | Trim Path |
| Pop In | Logos, buttons | Scale + Opacity |
| Morph | Icon transitions (hamburger→X) | Path keyframes |
| Stagger | Multiple elements | Delayed start times |
| Character | People, mascots | Parenting + bone hierarchy |
| Loader | Progress, spinners | Rotation + Trim Path |
| Frame-by-Frame | Walk/run cycles, complex characters | ip/op layer switching |
Pro Tip: For complex character animations (walk cycles, run cycles), use Frame-by-Frame technique instead of continuous animation. See references/professional-techniques.md
See: references/lottie-structure.md
Base Structure:
{
"v": "5.12.1",
"fr": 60,
"ip": 0,
"op": 120,
"w": 512,
"h": 512,
"nm": "Animation Name",
"ddd": 0,
"assets": [],
"layers": []
}
See: references/bezier-easing.md
| Use Case | Out Tangent | In Tangent |
|---|---|---|
| Entrance | [0.33, 0] | [0.67, 1] |
| Exit | [0.55, 0.055] | [0.675, 0.19] |
| Loop | [0.645, 0.045] | [0.355, 1] |
| Bounce | [0.34, 1.56] | [0.64, 1] |
| Spring | [0.5, 1.5] | [0.5, 0.9] |
# Validate JSON structure
python3 -c "import json; json.load(open('animation.json'))"
# Preview
echo "Open in: https://lottiefiles.com/preview"
See: references/shape-modifiers.md
{
"ty": "tm",
"s": {"a": 0, "k": 0},
"e": {
"a": 1,
"k": [
{"t": 0, "s": [0], "o": {"x": [0.33], "y": [0]}, "i": {"x": [0.67], "y": [1]}},
{"t": 45, "s": [100]}
]
},
"o": {"a": 0, "k": 0},
"m": 1
}
{
"ty": "rp",
"c": {"a": 0, "k": 8},
"tr": {
"r": {"a": 0, "k": 45},
"so": {"a": 0, "k": 100},
"eo": {"a": 0, "k": 30}
}
}
{
"ty": "op",
"a": {"a": 1, "k": [{"t": 0, "s": [0]}, {"t": 30, "s": [8]}]},
"lj": 2
}
See: references/advanced-animation.md and references/professional-techniques.md
The most professional technique for complex character animations. Instead of continuous animation, create multiple "poses" that appear/disappear in sequence using ip (in point) and op (out point).
{
"layers": [
{"nm": "Pose 1", "ip": 0, "op": 6, "shapes": [/* pose 1 */]},
{"nm": "Pose 2", "ip": 6, "op": 12, "shapes": [/* pose 2 */]},
{"nm": "Pose 3", "ip": 12, "op": 18, "shapes": [/* pose 3 */]}
]
}
Timing Formula: Total Frames = Poses × Frames_per_Pose → Duration = Total Frames / FPS
When to Use:
Use parent property to create hierarchies where moving one layer moves all children.
{
"layers": [
{"ind": 14, "nm": "Shadow", "ks": {"p": {"a": 0, "k": [340, 195, 0]}}},
{"ind": 1, "nm": "Head", "parent": 14, "ks": {"p": {"a": 0, "k": [88, -84, 0]}}},
{"ind": 2, "nm": "Body", "parent": 14, "ks": {"p": {"a": 0, "k": [0, -50, 0]}}}
]
}
Key Insight: Child positions are RELATIVE to parent. Moving Shadow moves all children with it.
Professional Parent Strategies:
Parent Chain Example:
Shadow (Parent for entire character)
├── Head (child)
├── Body (child)
├── Ear Inner (child)
├── Eye (child)
└── ... 13 total children
{
"ty": "sh",
"ks": {
"a": 1,
"k": [
{"t": 0, "s": [{"c": true, "v": [[0,0], [100,0], [100,100], [0,100]], "i": [...], "o": [...]}]},
{"t": 30, "s": [{"c": true, "v": [[50,-20], [120,50], [50,120], [-20,50]], "i": [...], "o": [...]}]}
]
}
}
Critical Rule: Both shapes MUST have identical vertex count for smooth morphing.
// Matte layer (defines visible area)
{"ind": 1, "nm": "Matte", "td": 1, "ty": 4, ...}
// Content layer (uses the matte)
{"ind": 2, "nm": "Content", "tt": 1, "ty": 4, ...}
| tt Value | Mode |
|---|---|
| 1 | Alpha Matte |
| 2 | Alpha Inverted |
| 3 | Luma Matte |
| 4 | Luma Inverted |
"s": {"a": 1, "k": [
{"t": 0, "s": [100, 100]},
{"t": 8, "s": [95, 105]}, // Slight crouch
{"t": 25, "s": [115, 90]}, // Main action
{"t": 40, "s": [100, 100]}
]}
// X * Y should stay roughly constant
{"t": 0, "s": [100, 100]}, // 10000
{"t": 10, "s": [120, 83]}, // 9960 ≈ preserved
{"t": 20, "s": [85, 118]} // 10030 ≈ preserved
{"ind": 1, "st": 0, "ip": 0},
{"ind": 2, "st": 3, "ip": 3}, // 3 frame delay
{"ind": 3, "st": 6, "ip": 6}, // 6 frame delay
{"ind": 4, "st": 9, "ip": 9} // 9 frame delay
"r": {"a": 1, "k": [
{"t": 0, "s": [0]},
{"t": 15, "s": [95]}, // Overshoot target
{"t": 25, "s": [88]}, // Settle back
{"t": 35, "s": [90]} // Final position
]}
{
"shapes": [
{"ty": "el", "s": {"a": 0, "k": [60, 60]}},
{"ty": "st", "w": {"a": 0, "k": 4}, "c": {"a": 0, "k": [0.2, 0.5, 1, 1]}, "lc": 2},
{"ty": "tm", "s": {"a": 0, "k": 0}, "e": {"a": 0, "k": 75},
"o": {"a": 1, "k": [{"t": 0, "s": [0]}, {"t": 60, "s": [360]}]}}
],
"ks": {"r": {"a": 1, "k": [{"t": 0, "s": [0]}, {"t": 120, "s": [360]}]}}
}
{
"shapes": [
{"ty": "sh", "ks": {"a": 0, "k": {"c": false, "v": [[20,50], [40,70], [80,30]], "i": [[0,0], [0,0], [0,0]], "o": [[0,0], [0,0], [0,0]]}}},
{"ty": "st", "w": {"a": 0, "k": 6}, "c": {"a": 0, "k": [0.2, 0.8, 0.4, 1]}, "lc": 2, "lj": 2},
{"ty": "tm", "e": {"a": 1, "k": [{"t": 0, "s": [0]}, {"t": 30, "s": [100]}]}}
]
}
"s": {"a": 1, "k": [
{"t": 0, "s": [100, 100]},
{"t": 8, "s": [115, 115]}, // Systole (Lub)
{"t": 12, "s": [90, 90]}, // Diastole start (Dub)
{"t": 18, "s": [105, 105]}, // Refill
{"t": 45, "s": [100, 100]} // Rest
]}
{
"ks": {
"s": {"a": 1, "k": [
{"t": 0, "s": [0, 0], "o": {"x": [0.34], "y": [1.56]}, "i": {"x": [0.64], "y": [1]}},
{"t": 18, "s": [110, 110], "o": {"x": [0.33], "y": [0]}, "i": {"x": [0.67], "y": [1]}},
{"t": 30, "s": [100, 100]}
]},
"o": {"a": 1, "k": [
{"t": 0, "s": [0]},
{"t": 12, "s": [100]}
]}
}
}
stroke-linecap="round" for Trim Path compatibilityFor professional character animations, combine stroke (contour) + fill (color) in each shape:
{
"ty": "gr",
"it": [
{"ty": "sh", "ks": {...}},
{"ty": "st", "c": {"a": 0, "k": [0.259, 0.153, 0.141, 1]}, "w": {"a": 0, "k": 1}, "lc": 2, "lj": 2},
{"ty": "fl", "c": {"a": 0, "k": [0.302, 0.604, 0.816, 1]}},
{"ty": "tr", ...}
]
}
Stroke Properties:
| Property | Value | Description |
|---|---|---|
lc (lineCap) | 1=Butt, 2=Round, 3=Square | Line end style |
lj (lineJoin) | 1=Miter, 2=Round, 3=Bevel | Corner style |
Professional Color Palette Example (from Running Cat):
{
"body_fill": [0.302, 0.604, 0.816, 1],
"outline": [0.259, 0.153, 0.141, 1],
"eye_white": [0.902, 0.976, 1.0, 1],
"shadow": [0.608, 0.706, 0.878, 1]
}
| Error | Cause | Solution |
|---|---|---|
| Non-looping | Last keyframe ≠ first value | Match start/end keyframe values |
| Stiff movement | No easing curves | Add bezier i/o tangents |
| Jerky animation | Keyframes too sparse | Add intermediate keyframes |
| Morph glitches | Different vertex counts | Add/remove vertices to match |
| Wrong rotation pivot | Incorrect anchor point | Set a to rotation center |
| Path draws wrong direction | Path not reversed | Use "d": 3 to reverse |
| Ugly character animation | Trying to morph complex shapes | Use frame-by-frame instead |
npx claudepluginhub rvanbaalen/skills --plugin lottie-animatorGenerates professional Lottie animations from static SVGs, replacing After Effects for motion graphics. Supports bezier curves, shape modifiers, character rigs, and frame-by-frame animation.
Animates static logos, UI elements, icons, and social media assets using AI presets and chat-based prompts. Exports to Lottie (JSON), GIF, or MP4.
Renders After Effects animations as Lottie JSON/dotLottie files in web and React apps using lottie-web, dotlottie-web, lottie-react for icons, micro-interactions, and loaders.