Files
cycle-atlas/.agents/skills/after-effects/references/expression-library.md
T

184 lines
6.9 KiB
Markdown
Raw Normal View History

2026-10-18 21:56:31 +00:00
# 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.