Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013TAaJBzbmePTECuv62BXYX
5.9 KiB
Expressions, Rigging & MOGRT
After Effects is GUI software, so this delivers knowledge: ready-to-paste JavaScript expressions, rigging setups that make motion controllable, and template/export pipelines. Expressions read on the property they are pasted on; value is that property's keyframed/static value, time is the composition time in seconds, and index, thisLayer, thisComp are in scope.
For a deeper cookbook (tuned inertial bounce, every loop variant, advanced per-axis wiggle, valueAtTime echoes, seedRandom grids, full rigging walkthrough, Essential Graphics → MOGRT steps, Lottie/Bodymovin + Media Encoder presets), see expression-library.md.
Core expressions
Inertial bounce (overshoot after the last keyframe)
Paste on a Position, Scale, or Rotation property. It continues the velocity at the final keyframe into a damped sine — the classic "settle" motion.
amp = 0.08; // overshoot amount
freq = 2.5; // oscillations per second
decay = 6.0; // how fast it settles
n = 0;
if (numKeys > 0) {
n = nearestKey(time).index;
if (key(n).time > time) n--;
}
if (n > 0) {
t = time - key(n).time;
v = velocityAtTime(key(n).time - 0.001);
value + v * (amp * Math.sin(freq * t * 2 * Math.PI) / Math.exp(decay * t));
} else {
value;
}
Looping
loopOut("cycle"); // repeat keyframed range forever
loopOut("pingpong"); // bounce back and forth
loopOut("offset"); // continue, accumulating (e.g. continuous travel)
loopOut("continue"); // extend final velocity linearly
loopOut("cycle", 2); // loop only the last 2 keyframes
loopIn("cycle"); // mirror, before the first keyframe
Wiggle and stable randomness
wiggle(2, 30); // 2 wiggles/sec, amplitude 30 (units match the property)
seedRandom(index, true); // unique-but-stable per layer; timeless=true
random(0, 100); // stable after seedRandom
wiggle(freq, amp, octaves=1, amp_mult=0.5, t=time); // full signature
seedRandom(index, true) before random() or wiggle() makes each layer differ but stay constant across renders — essential for grids of layers that must not flicker.
Time remap & value-at-time
// Sample another property/layer at a shifted time (echo/trailing motion)
delay = 0.2 * index;
thisComp.layer("Lead").transform.position.valueAtTime(time - delay);
// Speed up a precomp via time remap
linear(time, 0, thisComp.duration, 0, 6); // 6s source mapped over comp duration
Rigging
Make motion controllable instead of hand-keyed:
- Add a null/control layer (often a "Controls" layer). Add Slider Control, Checkbox Control, Color Control, Angle Control, or Point Control effects to it.
- Reference them with the pick-whip or by path:
ctrl = thisComp.layer("Controls");
amt = ctrl.effect("Intensity")("Slider"); // Slider Control → ADBE Slider Control-0001
on = ctrl.effect("Enable")("Checkbox"); // Checkbox: 1 or 0
col = ctrl.effect("Tint")("Color");
if (on == 1) value * amt else value;
- Parent transforms to a null so one move drives many layers. Use
toComp/fromCompto convert coordinate spaces when layers are parented or in different comps.
// Stagger N layers off one master slider
master = thisComp.layer("Controls").effect("Reveal")("Slider");
delay = 4 * index; // 4 frames per layer
master.valueAtTime(time - framesToTime(delay));
Essential Graphics / MOGRT
- Open Window → Essential Graphics, pick the comp as the Master.
- Drag the Slider/Checkbox/Color/Text source properties into the panel to expose them.
- Group, rename, and set comment fields for editors.
- Export Motion Graphics Template → a
.mogrtusable in Premiere Pro / AE. Keep driving expressions referencing the exposed controls so editors change only the exposed params.
Set "Allow fonts to substitute" off and embed/package fonts where possible so the template renders consistently elsewhere.
Export from expressions/template work
To Lottie (Bodymovin / @lottiefiles/bodymovin)
- Stick to Lottie-supported features: shape layers, transforms, masks, track mattes, basic expressions converted to keyframes.
- Avoid blur-heavy effects, blend modes, 3D layers, and most native effects — they don't translate.
- Bake expressions to keyframes if the renderer is strict, or use the
expressionsflag in Bodymovin and test on the target player (web/iOS/Android renderers differ). - Run Bodymovin → Render to produce
data.json(+ optional images). Verify in a Lottie preview before handoff.
To video (Media Encoder)
- File → Export → Add to Adobe Media Encoder Queue (or render queue for AE-native).
- Delivery: H.264 (MP4), bitrate ~10–20 Mbps for 1080p, VBR 2-pass.
- Master/intermediate: ProRes 422 HQ (or ProRes 4444 when alpha is needed).
- Transparency: ProRes 4444 or PNG/QuickTime with an alpha channel; H.264 cannot carry alpha. (See
export-recipes.mdfor the full codec/alpha/bitrate matrix.)
Quick reference
| Goal | Expression |
|---|---|
| Loop keyframes | loopOut("cycle") |
| Continuous travel | loopOut("offset") |
| Subtle life | wiggle(2, 20) |
| Stable per-layer random | seedRandom(index,true); random(...) |
| Settle/overshoot | inertial bounce (above) |
| Echo another layer | valueAtTime(time - delay) |
| Read a slider | effect("Name")("Slider") |
| Frames ↔ seconds | framesToTime(n) / timeToFrames(t) |
Gotchas
- An expression overrides keyframes on that property unless it incorporates
value; start most expressions fromvalue. indexis the layer's stacking number — it changes if layers are reordered; prefer named lookups for stable rigs.- Expression errors disable the expression and show a yellow banner; check the property's path names (effect names must match exactly, including duplicates' suffixes).
- Pre-compose for reuse; name layers; use shy/lock and guide layers for safe areas before handoff.