Files
cycle-atlas/.agents/skills/after-effects/references/expression-library.md
T
Claude d4b3cf1b85 Add motion design skills pack
Installed via npx skills add iart-ai/motion-design-skills. Kept the
project's existing remotion-video skill unchanged.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E35uEC1pGu95tUpM4b815L
2026-10-18 21:56:31 +00:00

185 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# After Effects Expression Library, Rigging & Export
A deeper cookbook. All expressions are JavaScript (the modern AE expression engine). They evaluate on the property they are pasted on, where `value`, `time`, `index`, `thisLayer`, `thisComp` are in scope.
## Inertial bounce (parameterized)
```js
// Overshoot/settle after the most recent keyframe. Tune amp/freq/decay.
amp = 0.10; // 0.05 = subtle, 0.2 = bouncy
freq = 3.0; // oscillations per second
decay = 5.0; // higher = settles faster
n = 0;
if (numKeys > 0) {
n = nearestKey(time).index;
if (key(n).time > time) n--;
}
if (n === 0) {
value;
} else {
t = time - key(n).time;
v = velocityAtTime(key(n).time - thisComp.frameDuration / 10);
value + v * amp * Math.sin(freq * t * 2 * Math.PI) / Math.exp(decay * t);
}
```
Inertial bounce works on multi-dimensional properties because `velocityAtTime` returns a vector; the arithmetic is per-component.
## Loop variants
```js
loopOut("cycle"); // A B C A B C ...
loopOut("pingpong"); // A B C B A B C ...
loopOut("offset"); // continues accumulating the delta each cycle
loopOut("continue"); // linear extension of the final velocity (no loop)
loopOut("cycle", 3); // loop only the last 3 keyframes
loopIn("cycle", 2); // loop the first 2 keyframes, backwards in time
loopOutDuration("cycle", 2); // loop the last 2 SECONDS of keyframes
```
Use `offset` for endless conveyor/scroll motion; `continue` for inertia past the last keyframe without oscillation.
## Wiggle — advanced
```js
// Full signature: wiggle(freq, amp, octaves, amp_mult, time)
wiggle(2, 30, 3, 0.5); // 3 octaves adds finer detail
// Per-axis wiggle (different amplitude X vs Y)
x = wiggle(2, 50)[0];
y = wiggle(2, 10)[1];
[x, y];
// Wiggle only rotation while keeping keyframed position
wiggle(1, 5); // on Rotation
// Smooth, looping ambient motion without true wiggle (loopable):
amp = 20; period = 4; // seconds
[Math.sin(time / period * 2 * Math.PI) * amp,
Math.cos(time / period * 2 * Math.PI) * amp] + value;
```
`wiggle` is non-looping noise; for seamless loops use periodic sin/cos as above.
## Stable randomness across a grid
```js
seedRandom(index, true); // timeless=true → constant over time, varies per layer
startDelay = random(0, 0.5); // each layer gets a stable random delay
opacity = ease(time, startDelay, startDelay + 0.4, 0, 100);
```
`seedRandom(index, false)` (timeless=false) lets `random()` vary over time — use for flicker; `true` for stable offsets.
## Time remap & valueAtTime echoes
```js
// Trailing/echo: sample the lead layer in the past, staggered by index
delay = 0.08 * (index - 1);
thisComp.layer("Lead").transform.position.valueAtTime(time - delay);
// Speed-ramp a time-remapped layer using easing on the source time
src = thisComp.layer("Source");
linear(time, 0, 2, 0, src.source.duration); // play a 2s window of the source
// Sample own value in the past for motion smear / trail
valueAtTime(time - 0.1);
```
## Rigging walkthrough
### Control types and how to read them
```js
ctrl = thisComp.layer("Controls");
ctrl.effect("Intensity")("Slider"); // number
ctrl.effect("Visible")("Checkbox"); // 1 or 0
ctrl.effect("Brand")("Color"); // [r,g,b,a] 0..1
ctrl.effect("Spin")("Angle"); // degrees
ctrl.effect("Anchor")("Point"); // [x,y]
```
### One slider, staggered reveal across N layers
```js
// On each layer's Opacity:
master = thisComp.layer("Controls").effect("Reveal")("Slider"); // 0..100 driver
per = 6; // frames of stagger per layer
shift = framesToTime(per * (index - 1));
ease(master, 0, 100, 0, 100) * (time > shift ? 1 : 0);
```
### Coordinate-space conversions
```js
// Place this layer where another parented layer appears in comp space
target = thisComp.layer("Marker");
fromComp(target.toComp(target.anchorPoint));
// World position of a point on this layer
toComp([0, 0]);
```
`toComp` converts layer space → composition space; `fromComp` does the inverse. Use them whenever layers are parented or live in different (nested) comps.
### Linking many layers to a master null
1. Select all children → set Parent to the null.
2. Animate only the null; children inherit transform.
3. For non-transform links (effects, opacity), pick-whip to the control layer's effect.
## Essential Graphics / MOGRT export steps
1. **Window → Essential Graphics**, choose the master comp.
2. Drag exposed properties (Slider, Checkbox, Color, Text Source, Media replacement) into the panel.
3. Add **Group** headers, rename controls, fill comment fields for editors.
4. Use **Drop-Zone / Media Replacement** for swappable footage/logos.
5. Click **Export Motion Graphics Template**, choose destination (Local Templates Folder / Library / file). Toggle "Make fonts available" and check "Raster/vector" compatibility for Premiere.
6. Test in Premiere Pro's Essential Graphics → Browse panel.
Keep all motion driven by expressions referencing the exposed controls so editors only touch the exposed params; hide internal layers with shy.
## Lottie / Bodymovin export
Supported reliably:
- Shape layers, solids, transforms (position/scale/rotation/opacity/anchor).
- Masks and track mattes (alpha), parenting, basic gradients.
- Trim Paths, simple repeaters.
- Expressions: enable in Bodymovin settings, but verify on the target renderer — `lottie-web`, lottie-ios, and lottie-android differ in expression and effect support.
Not supported / risky (bake or avoid):
- Blend modes, most native Effects, layer blurs, 3D layers/cameras, time remapping, adjustment-layer effects.
Workflow:
1. Install Bodymovin extension; **Window → Extensions → Bodymovin**.
2. Select comp(s), set destination, choose Standard/Demo.
3. Settings: enable "Glyphs"/"Hidden", "Expressions" only if needed; "Assets" → export images or use base64.
4. Render `data.json`. Preview in a Lottie player; check file size and that masks/mattes survived.
5. For web, load with `lottie-web`:
```js
import lottie from 'lottie-web';
lottie.loadAnimation({
container: document.getElementById('lottie'),
renderer: 'svg', // 'canvas' for heavy fills, better perf
loop: true, autoplay: true,
path: '/data.json',
});
```
## Media Encoder presets
| Use | Codec / format | Settings |
|---|---|---|
| Web/social delivery | H.264 (MP4) | VBR 2-pass, 1080p ~12–16 Mbps; 4K ~35–50 Mbps |
| Master/intermediate | ProRes 422 HQ (MOV) | full range, matched fps |
| With alpha | ProRes 4444 (MOV) | enable alpha channel |
| Lossless interchange | PNG sequence or ProRes 4444 | per-frame, alpha |
| GIF | via Media Encoder/Photoshop | reduce palette, dither, cap dimensions |
Tips:
- Match the comp frame rate; avoid frame-blending unless intentionally retiming.
- H.264 cannot store alpha — composite onto a background or use ProRes 4444 / PNG.
- For crisp text, render at the delivery resolution (don't upscale); set quality to maximum and use 2-pass VBR.