After Effects expressions
After Effects expressions: a copy-and-paste cheat sheet
Most After Effects projects lean on the same dozen expressions: wiggle, loopOut, a bounce, a delayed follow, time-based rotation, a remap with linear() or ease(), randomness and a slider to drive it all. Here is each one ready to paste, with a line on what it does. In After Effects you Alt-click (Option-click) a property's stopwatch and type. Each snippet also says whether it runs as written in Premation's expression engine — checked against the interpreter's own function table — and, when it does not, the version that does.
Before you paste into Premation
Where expressions go
Premation's expression editor is in the Graph panel (Window ▸ Panels ▸ Graph Panel): pick a property of the selected layer and type. Alt+Shift+= adds an expression to the selected property and opens the editor, as in After Effects. Source Text takes one through Layer → Text → Source Text Expression….
One expression, not a script
Premation evaluates a single JavaScript expression: no semicolons, no variables, no if blocks and no // comments. Most multi-line After Effects expressions fold into one line with the ternary operator (condition ? a : b); the rewrites below show how.
Each axis is evaluated on its own
On Position, Scale or Anchor Point the expression runs once per axis, and value is that axis's number, not an array. An array result is read by axis — the first item drives X, the second Y — so After Effects' value + [100, 0] becomes [value + 100, value], and value[1] becomes value.
Controls are ctrl('Name')
After Effects reads a Slider Control as effect("Slider Control")("Slider"). Premation's expression controls — Slider, Angle, Point, Colour, Checkbox, Dropdown, Layer, added from the Animate menu — are read by name: ctrl('Slider Control'). effect() is not defined.
Other layers by name
There is no index and no transform group. Read another layer with thisComp.layer('Leader').position, or one property at any time with layerAt('Leader', 'x', time - 0.1).
Same answer every render
Expressions run in the native engine's own interpreter, never a JavaScript eval, so the viewport, an export and a command-line render agree. wiggle() and random() are seeded per layer and property, so two exports of one project match.
Wiggle
wiggle(frequency, amplitude) adds smooth random motion around the property's value: frequency in wiggles per second, amplitude in the property's units.
wiggle(2, 30)[wiggle(2, 30)[0], value[1]][wiggle(2, 30), value]wiggle(effect("Frequency")("Slider"), effect("Amount")("Slider"))wiggle(ctrl('Frequency'), ctrl('Amount'))Loop keyframes: loopOut and loopIn
The expression to repeat keyframes. loopOut() repeats the keyframed animation after the last keyframe; loopIn() does the same before the first. In Premation both loop the whole first-to-last keyframe range: the second argument After Effects accepts (how many keyframes to loop) is ignored.
loopOut()loopOut("cycle")loopOut("pingpong")loopOut("offset")loopOut("continue")loopIn("cycle")Spin and oscillate with time
time is the current time in seconds, so multiplying it gives a constant rate. Math.sin gives a back-and-forth.
time * 360value + time * 90value + Math.sin(time * 2 * Math.PI) * 1550 + Math.sin(time * 4) * 50Bounce and inertial bounce
An inertial bounce lets a property overshoot and settle after a keyframe, using the speed it arrived with. The classic After Effects version is a short script with variables, so it does not run in Premation; the single-expression version below does the same after the last keyframe and also runs in After Effects.
amp = 0.05; freq = 4; decay = 8;
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);
}numKeys === 0 || time <= key(numKeys).time ? value : value + velocityAtTime(key(numKeys).time - 0.001) * 0.05 * Math.sin((time - key(numKeys).time) * 4 * 2 * Math.PI) / Math.exp((time - key(numKeys).time) * 8)value + Math.sin(time * 12) * 40 / Math.exp(time * 4)Delay and follow another layer
A follower that copies a leader's motion a beat late. After Effects users usually chain layers with index - 1; Premation has no index, so name the leader.
thisComp.layer(index - 1).transform.position.valueAtTime(time - 0.1)[layerAt('Leader', 'x', time - 0.1), layerAt('Leader', 'y', time - 0.1)]layerAt('Leader', 'rotation', time - 0.1)thisComp.layer('Leader').positionvalueAtTime(time - 0.5)Stepped motion: posterizeTime
Makes a smooth expression update only a few times a second, for a hand-animated feel. In After Effects posterizeTime(fps) is a statement placed before the expression; in Premation it returns the stepped time, which you pass where the time goes.
posterizeTime(8); wiggle(2, 30)wiggle(2, 30, 1, 0.5, posterizeTime(8))valueAtTime(posterizeTime(12))Clamp and remap: clamp, linear, ease
clamp(value, min, max) keeps a number inside limits. linear(t, tMin, tMax, a, b) maps t from one range onto another; ease(), easeIn() and easeOut() do the same with a curve (Premation's ease() is a smoothstep).
clamp(value, 0, 100)linear(time, 0, 2, 0, 360)ease(time, 1, 3, 0, 100)linear(effect("Progress")("Slider"), 0, 100, 0, 1920)linear(ctrl('Progress'), 0, 100, 0, 1920)linear(time, 0, 1, [0, 0], [960, 540])[linear(time, 0, 1, 0, 960), linear(time, 0, 1, 0, 540)]Measure a layer: sourceRectAtTime
sourceRectAtTime() returns a layer's own bounds — top, left, width and height — at a time, which is how motion adapts to content instead of typed numbers. Premation measures only the layer the expression is on; there is no thisComp.layer(…).sourceRectAtTime().
[sourceRectAtTime().left + sourceRectAtTime().width / 2, sourceRectAtTime().top + sourceRectAtTime().height / 2]s = thisComp.layer("Title").sourceRectAtTime(); [s.width + 40, s.height + 20]Random values: random and seedRandom
random(min, max) returns a new number every frame. seedRandom(seed, true) fixes it, so a layer keeps one random value. In Premation seedRandom returns 0, so it is added in front of random() inside the one expression. Without seedRandom, Premation already seeds each layer and each axis differently.
value + random(-5, 5)seedRandom(5, true); random(0, 100)seedRandom(5, true) + random(0, 100)seedRandom(index, true); random([0, 0], [thisComp.width, thisComp.height])[seedRandom(5, true) + random(0, thisComp.width), random(0, thisComp.height)]Which ones work in Premation
| Expression | What it does | Works in Premation |
|---|---|---|
| wiggle(2, 30) | Smooth random motion around the value | Yes |
| [wiggle(2, 30)[0], value[1]] | Wiggle one axis only | Needs rewrite: [wiggle(2, 30), value] — value is per axis |
| loopOut() / loopOut("cycle") | Repeat the keyframes after the last one | Yes |
| loopOut("pingpong" / "offset" / "continue") | Loop back and forth / stack / keep going | Yes |
| loopOut("cycle", 2) | Loop only the last few keyframes | Partly: the count is ignored; the whole range loops |
| loopIn("cycle") | Repeat the keyframes before the first one | Yes |
| time * 360 | Constant rotation | Yes |
| value + Math.sin(time * 2 * Math.PI) * 15 | Oscillate around the value | Yes |
| Inertial bounce (script form) | Overshoot and settle after keyframes | Needs rewrite: single ternary expression (above) |
| thisComp.layer(index - 1).transform.position.valueAtTime(time - 0.1) | Follow the layer above with a delay | Needs rewrite: no index or transform — layerAt('Leader', 'x', time - 0.1) |
| valueAtTime(time - 0.5) | This property's own earlier value | Yes |
| posterizeTime(8); wiggle(2, 30) | Stepped, low-frame-rate wiggle | Needs rewrite: wiggle(2, 30, 1, 0.5, posterizeTime(8)) |
| clamp(value, 0, 100) | Keep a number inside limits | Yes |
| linear(time, 0, 2, 0, 360) / ease(…) | Remap one range onto another | Yes, with numbers; for arrays, one linear() per axis |
| [sourceRectAtTime().left + sourceRectAtTime().width / 2, …] | Centre the anchor on a layer's content | Yes (own layer only) |
| thisComp.layer("Title").sourceRectAtTime() | Size a box to another layer | No: only the expression's own layer can be measured |
| seedRandom(5, true); random(0, 100) | A fixed random value | Needs rewrite: seedRandom(5, true) + random(0, 100) |
| value + random(-5, 5) | Per-frame jitter | Yes |
| effect("Slider Control")("Slider") | Read a Slider Control | Needs rewrite: ctrl('Slider Control') |
| degreesToRadians(45) | Degrees to radians | Needs rewrite: 45 * Math.PI / 180 |
Questions
- What is the wiggle expression in After Effects?
- wiggle(frequency, amplitude) — for example wiggle(2, 30) shakes a property about twice a second by up to 30 units. Optional arguments add octaves of detail, set how much each octave is scaled, and give the time to sample, which is how posterizeTime() can be passed in.
- What is the expression to loop keyframes in After Effects?
- loopOut() on the keyframed property. It cycles by default; loopOut("pingpong") plays back and forth, "offset" stacks each repeat on the last, and "continue" carries on at the final speed. loopIn() loops before the first keyframe instead.
- How do I make a bounce with an expression?
- Use an inertial bounce: after a keyframe, add the arrival velocity multiplied by a sine wave that dies away with Math.exp(). The cheat sheet above has a script form for After Effects and a one-line form that also runs in Premation.
- How do I link an expression to a slider?
- Add a Slider Control to the layer, then read it: effect("Slider Control")("Slider") in After Effects, or ctrl('Slider Control') in Premation. A slider can be keyframed, which animates the expression's input rather than the property itself.
- Do After Effects expressions work in Premation?
- Many run as written — wiggle, loopOut, loopIn, valueAtTime, velocityAtTime, key(), clamp, linear, ease, random, Math — because Premation's interpreter implements After Effects' expression functions. Script-style expressions with semicolons or variables, effect(), index and vector maths on value need the one-line rewrites shown on this page.
- Can I turn an expression into keyframes?
- Yes. In After Effects use Animation ▸ Keyframe Assistant ▸ Convert Expression to Keyframes; in Premation, Animation → Convert Expression to Keyframes. Both sample the expression across the range and write ordinary keyframes you can edit by hand.