Skip to content
Documentation ▾

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.

NameTypeWhat it is
#timenumberSeconds since the start of the composition — the playhead.
#framenumberThe frame number under the playhead, counted at the composition’s own rate.
#fpsnumberFrames per second of the composition this layer lives in.
#progressnumberHow 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.

NameTypeWhat it is
#layerlayerThe 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.timenumberSeconds since this layer started — 0 on its first frame, however late it begins. Shorthand for #time − #layer.start.
#layer.progressnumberHow far through this layer’s own duration the playhead is, 0 to 1. Shorthand for #layer.time / #layer.duration.
#layer.durationnumberHow long this layer lasts, in seconds.
#layer.startnumberWhen this layer begins, in composition seconds.
#layer.endnumberWhen this layer ends, in composition seconds. Shorthand for #layer.start + #layer.duration.
#layer.indexnumberThis layer’s stacking position — 0 is the topmost layer in the composition.
#layer.widthnumberThe layer’s own width in pixels, before scaling.
#layer.heightnumberThe layer’s own height in pixels, before scaling.
#layer.opacitynumberThe layer’s opacity, 0 to 1.

Composition

The frame the layer lives in.

NameTypeWhat it is
#comp.widthnumberThe composition’s width in pixels.
#comp.heightnumberThe composition’s height in pixels.
#comp.durationnumberHow long the composition runs, in seconds.
#comp.framesnumberHow many frames the composition holds at its own rate. Shorthand for #comp.duration × #fps.

Playback

What the editor is doing right now.

NameTypeWhat it is
#playingbooleanTrue while the timeline is playing, false while you scrub or sit still.

Randomness

The seed behind random() and wiggle().

NameTypeWhat it is
#seednumberThis 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.

SignatureWhat 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.

SignatureWhat 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.

SignatureWhat 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.

SignatureWhat 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.

SignatureWhat 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.

SignatureWhat 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.

SignatureWhat 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.

SignatureWhat 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.

SignatureWhat 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.