Expression language reference

An expression is a small formula that drives an animatable property's value on every frame. You write it in the Expression section of the keyframe panel; this page is the reference for the language itself — the values you can read, the functions you can call, and the syntax the editor accepts. For how to open the editor, enable an expression, and link properties with the pick whip, see Animate with expressions.

Every expression evaluates to a single value at the current time. The last expression in your code is the result. Sequence re-runs the whole formula each frame, so anything that depends on time animates automatically.

The Expression section of the keyframe panel with a formula in the code editor and its live evaluated value above.

Globals#

These values are always in scope. Read them directly by name.

Globals

Note

velocity and speed are also in scope but are reserved — they currently evaluate to 0 and don't yet report a property's rate of change. Don't build a formula that depends on them.

Built-in functions#

Interpolation#

Map an input across a range to an output range. linear and the ease family clamp their result to the val1val2 range; lerp does not.

  • linear(t, tMin, tMax, val1, val2) — Straight-line interpolation. As t moves from tMin to tMax, the result moves from val1 to val2.
  • ease(t, tMin, tMax, val1, val2) — Same mapping with an S-curve (eases in and out).
  • easeIn(t, tMin, tMax, val1, val2) — Starts slow, accelerates.
  • easeOut(t, tMin, tMax, val1, val2) — Starts fast, decelerates.
  • lerp(a, b, t) — Unclamped blend between a and b by fraction t.
  • clamp(value, min, max) — Constrain value to the range minmax.

Noise and randomness#

Random output is deterministic — the same frame always produces the same value — so playback and export match. The seed is derived from the property and the frame.

  • wiggle(freq, amp, octaves?) — Smooth random motion: freq wiggles per second, amp maximum deviation. octaves adds finer layers of detail.
  • noise(t) — 1D value noise in the range -1 to 1.
  • random(min?, max?) — A random number. With no arguments, between 0 and 1.
  • gaussRandom() — A random number on a Gaussian (bell-curve) distribution.

Looping#

Repeat your keyframed animation before the first keyframe or after the last one. The keyframes and current time are supplied automatically — you only pass the mode.

  • loopOut(mode) — Loop after the last keyframe.
  • loopIn(mode) — Loop before the first keyframe.

mode is one of "cycle" (default — repeat from the start), "pingpong" (alternate forward and back), "offset" (repeat, accumulating the total change each cycle), or "continue" (hold the ending velocity). Omit mode to get "cycle".

Keyframe access#

Read this property's own keyframes.

  • key(index) — The keyframe at a 1-based index, as { time, value, id }.
  • nearestKey(time) — The keyframe closest to time.
  • valueAtTime(time) — This property's interpolated value at any time.

Element and property references#

Read another property's value so two properties stay linked. Build a reference by chaining .effect() and .property() from an element:

element("Title Card").effect("seq.video.transform").property("x-position");
  • thisElement — The element the expression lives on.
  • element(name) — Another element, by its name or story-tree path.
  • .effect(name) — An effect on that element.
  • .property(name) — A property on that effect. This is the value the reference resolves to.

You can chain .valueAtTime(time) onto a property reference to read its value at a specific time rather than the current one.

Dragging the pick whip onto a property writes one of these references for you: a same-element target becomes thisElement.effect(...).property(...), and a different element becomes element("Name").effect(...).property(...). See Animate with expressions for the pick-whip workflow.

Note

References can't form a loop. If property A reads property B, then B can't be made to read A — Sequence rejects a pick-whip drop that would create a cycle with "Would create a cycle in expression dependencies," and validates the same rule for typed references.

Vector math#

Operate on arrays of numbers (for example a [x, y] position).

  • length(vec) — Magnitude of the vector.
  • normalize(vec) — The vector scaled to length 1.
  • dot(a, b) — Dot product.
  • cross(a, b) — Cross product.

Data sources#

Drive animation from an external data stream (JSON or CSV) attached to the project. Values are linearly interpolated between samples.

  • data(sourceName, streamName, time) — The stream's value at time.
  • dataKeys(sourceName, streamName) — All time keys in the stream.
  • dataKeyCount(sourceName, streamName) — How many keys the stream has.

Math and array methods#

The full JavaScript Math object is available: Math.sin, Math.cos, Math.abs, Math.floor, Math.round, Math.min, Math.max, Math.sqrt, Math.pow, Math.PI, and the rest.

Arrays support map, filter, reduce, find, indexOf, slice, and includes.

Syntax#

The engine runs a restricted subset of JavaScript — enough to compute a value, nothing that can reach outside the frame.

You can use:

  • Number, string, boolean, null, array, object, and template-literal values
  • Arithmetic (+ - * / %), comparison (== != === !== < > <= >=), logical (&& || ??), bitwise (& | ^ << >>), and unary (- ! ~ typeof) operators
  • The ternary conditional, condition ? a : b
  • const and let declarations, including destructuring
  • Arrow functions with an expression body, such as (a, b) => a + b
  • Multiple statements in a block — the last one is the returned value

You can't use:

  • Loops (for, while), if, or switch — use the ternary ? : instead
  • Function or class declarations, or this — use thisElement
  • try/catch/throw, regular expressions, eval, window, or document

Execution limits

Each expression runs under a budget — roughly 5 ms of wall-clock time and 50,000 evaluation steps per frame. A formula that exceeds the budget stops with an error instead of stalling playback.

Examples#

Ease a rotation from 0° to 360° over the first five seconds:

ease(time, 0, 5, 0, 360);

Add a continuous shake on top of the property's existing animation:

value + wiggle(5, 10);

Follow another element's horizontal position so a title tracks a shape:

element("Title Card").effect("seq.video.transform").property("x-position");

Drive scale from a slider control on the same element:

const amount = thisElement
.effect("seq.utility.slider_control")
.property("value");
value * amount;

Show the property only between 2 and 5 seconds, hidden otherwise:

time &gt;= 2 &amp;&amp; time &lt;= 5 ? 100 : 0;

Loop a keyframed animation back and forth forever:

loopOut("pingpong");

Map an imported speed reading onto a playback range:

const speed = data("telemetry.json", "speed", time);
linear(speed, 0, 200, 1.0, 2.5);
Was this page helpful?