Animate
Expressions
A small formula in place of a value. Read the clock, the composition, this layer or any other, and the field computes itself on every frame.
Write one anywhere
Every field that holds a value can hold a formula instead. The quickest way in is to type it: click a field and write #frame, or #layer.rotation * 2, or wiggle(2, 10), and press Enter. The field turns purple — it is an expression now. Click it again to open the editor, or hold ⌥ and click to detach it, keeping whatever value was on screen.
Right-clicking any field offers the same thing by name (Write an expression…), alongside binding it to a variable. A field whose value is computed cannot also be keyframed — detach it first, and the keyframes that were underneath come back untouched.
If a formula stops working, the field keeps showing the last value that made sense and turns red rather than snapping to zero, and hovering it says what is wrong. An expression that cannot run should never move your layer.
Types
An expression has a type, and it is the same type system the node board's wires use — number, vector, color, boolean, text and layer. A formula whose result does not fit the field is an error you see while typing, not a surprise at render time. Text that looks like a colour is a colour: "#ff8732" in a fill means what you would expect.
Reading a layer
#layer is the layer the expression is attached to, and you read values off it by name: #layer.rotation, #layer.opacity, #layer.scale, #layer.radius.tl. The list of what a layer offers is exactly the list its card shows on the node board — one projection behind both — so anything you can wire, you can write.
Other layers are reached by name with layer("Title"), and read the same way: layer("Title").x + 40 pins one layer beside another. Names come from the timeline, so renaming a layer is visible in the formula rather than hidden behind an id.
Globals
Everything the host knows, written with a leading #. Some need a layer or a composition to answer; used where there is none, the editor greys them out and says so.
Time
Where the playhead is.
| Name | Type | What it is |
|---|---|---|
| #time | number | Seconds since the start of the composition — the playhead. |
| #frame | number | The frame number under the playhead, counted at the composition’s own rate. |
| #fps | number | Frames per second of the composition this layer lives in. |
| #progress | number | How far through the composition the playhead is: 0 at the start, 1 at the end. Shorthand for #time / #comp.duration. |
Layer
The layer this expression is attached to.
| Name | Type | What it is |
|---|---|---|
| #layer | layer | The layer this expression is attached to. Read any of its values off it — #layer.rotation, #layer.opacity, #layer.fill.<id>.color — the same list its node card shows. |
| #layer.time | number | Seconds since this layer started — 0 on its first frame, however late it begins. Shorthand for #time − #layer.start. |
| #layer.progress | number | How far through this layer’s own duration the playhead is, 0 to 1. Shorthand for #layer.time / #layer.duration. |
| #layer.duration | number | How long this layer lasts, in seconds. |
| #layer.start | number | When this layer begins, in composition seconds. |
| #layer.end | number | When this layer ends, in composition seconds. Shorthand for #layer.start + #layer.duration. |
| #layer.index | number | This layer’s stacking position — 0 is the topmost layer in the composition. |
| #layer.width | number | The layer’s own width in pixels, before scaling. |
| #layer.height | number | The layer’s own height in pixels, before scaling. |
| #layer.opacity | number | The layer’s opacity, 0 to 1. |
Composition
The frame the layer lives in.
| Name | Type | What it is |
|---|---|---|
| #comp.width | number | The composition’s width in pixels. |
| #comp.height | number | The composition’s height in pixels. |
| #comp.duration | number | How long the composition runs, in seconds. |
| #comp.frames | number | How many frames the composition holds at its own rate. Shorthand for #comp.duration × #fps. |
Playback
What the editor is doing right now.
| Name | Type | What it is |
|---|---|---|
| #playing | boolean | True while the timeline is playing, false while you scrub or sit still. |
Randomness
The seed behind random() and wiggle().
| Name | Type | What it is |
|---|---|---|
| #seed | number | This field’s own seed. It never changes as time moves, so random() and wiggle() stay identical on every replay — and two fields with the same expression still differ. |
Functions
Math
Arithmetic and rounding.
| Signature | What it does |
|---|---|
| abs(value) | Distance from zero — drops the minus sign. abs(-4) → 4 |
| sign(value) | −1, 0 or 1, depending on which side of zero the value is. |
| floor(value) | Rounds down to a whole number. floor(2.9) → 2 |
| ceil(value) | Rounds up to a whole number. |
| round(value) | Rounds to the nearest whole number. |
| sqrt(value) | Square root. Negative input gives 0 rather than an error. |
| exp(value) | e raised to this power. |
| log(value) | Natural logarithm. Zero or less gives 0 rather than an error. |
| fract(value) | Just the part after the decimal point — 0 to 1, and it loops. fract(#time) loops once a second |
| min(a, b) | The smaller of two numbers. |
| max(a, b) | The larger of two numbers. |
| pow(value, exponent) | The first number raised to the power of the second. |
| mod(value, length) | The remainder after dividing — the usual way to make something repeat. mod(#time, 2) counts 0→2 over and over |
| clamp(value, min, max) | Holds a number inside a range — anything below the minimum becomes the minimum, and the same at the top. clamp(#progress, 0, 1) |
Trigonometry
Angles, waves and circles. Angles are in radians.
| Signature | What it does |
|---|---|
| sin(value) | Sine — a smooth wave from −1 to 1. Angles are in radians. sin(#time * 3) * 20 |
| cos(value) | Cosine — the same wave as sine, a quarter turn ahead. |
| tan(value) | Tangent. |
| asin(value) | The angle whose sine is this value. |
| acos(value) | The angle whose cosine is this value. |
| atan(value) | The angle whose tangent is this value. |
| atan2(y, x) | The angle from the origin to a point — the reliable way to aim one thing at another. |
| radians(value) | Turns degrees into the radians every angle function here expects. radians(90) |
| degrees(value) | Turns radians back into degrees. |
Interpolation
Blending and remapping ranges — the heart of most expressions.
| Signature | What it does |
|---|---|
| mix(a, b, t) | Blends smoothly from the first value to the second. Works on numbers, colours and vectors alike. mix("#ff8732", "#ff2885", #progress) |
| map(value, fromMin, fromMax, toMin, toMax) | Rescales a number from one range to another. It keeps going past the ends — wrap it in clamp() if you want it to stop there. map(#layer.time, 0, 2, 0, 100) |
| smoothstep(edge0, edge1, value) | An eased 0→1 ramp between two edges: flat, then smooth, then flat again. The gentle alternative to a hard cut. smoothstep(0, 1, #layer.time) |
| pingpong(value, length) | Bounces back and forth between 0 and the length instead of jumping back to the start the way mod() does. pingpong(#time, 1) |
Random
Repeatable randomness: the same wobble every time you play.
| Signature | What it does |
|---|---|
| random([min], [max]) | A fixed random number for this field — the same every frame and every replay, so nothing flickers. Call it with no arguments for 0 to 1. random(-10, 10) |
| noise(value) | Smooth randomness from 0 to 1: wanders rather than jumps, and repeats exactly on every replay. noise(#time * 2) |
| wiggle(frequency, amount) | Organic drift around zero — add it to a value to make it breathe. Repeats exactly on every replay, and two wiggles in one expression never move together. 100 + wiggle(2, 8) |
Color
Build and blend colours.
| Signature | What it does |
|---|---|
| rgb(r, g, b) | Builds a colour from red, green and blue, each 0 to 1. rgb(1, 0.5, 0) |
| rgba(r, g, b, a) | Builds a colour from red, green, blue and opacity. |
| hsl(h, s, l) | Builds a colour from hue, saturation and lightness — the easy way to cycle through a rainbow. hsl(#time * 60, 0.8, 0.5) |
| hsla(h, s, l, a) | Builds a colour from hue, saturation, lightness and opacity. |
Vector
Two-component values, for positions and sizes.
| Signature | What it does |
|---|---|
| vec(x, y) | Builds a two-part value from an X and a Y. vec(#comp.width / 2, 0) |
| length(value) | How long something is: the magnitude of a vector, or the number of characters in a piece of text. |
| distance(a, b) | The straight-line distance between two points. |
| dot(a, b) | The dot product of two vectors. |
| normalize(value) | Keeps a vector’s direction but makes its length exactly 1. |
Text
Turn values into text — counters, labels, padded numbers.
| Signature | What it does |
|---|---|
| str(value) | Turns any value into text. |
| pad(value, digits) | Writes a whole number with leading zeros — what a counter or a timecode needs. pad(#frame, 4) → “0042” |
| fixed(value, decimals) | Writes a number with a fixed number of decimal places. fixed(#progress * 100, 1) + “%” |
| upper(value) | Turns text into capitals. |
| lower(value) | Turns text into lowercase. |
Logic
Choose between two values.
| Signature | What it does |
|---|---|
| if(condition, then, otherwise) | Picks one of two values. The same as writing condition ? then : otherwise. if(#playing, 1, 0.4) |
Layers
Read values off other layers in the composition.
| Signature | What it does |
|---|---|
| layer(name, [property]) | Another layer, by the name the timeline shows. Read any of its values off it with a dot — the same list its node card offers — so one layer can follow another, or a whole row can offset from a single leader. layer("Title").x + 40 |
Expressions and nodes
The same value can come from a written formula or from the node board, and they are two views of one system rather than two systems: an Expression node puts a formula on the board with sockets on it, and a layer offers the same properties to both. Orange fields are driven by nodes, purple by an expression, and either way clicking the field opens the thing that computes it.