Command Palette

Search for a command to run...

Understanding State Machines

Explains how state machines work in the dotLottie Web Player. Covers the core model, workflow, API, events, transitions, guards, inputs, interactions, and actions.

Understanding State Machines

State machines let you define complex animation behaviors triggered by user interactions and application events. You define the logic inside your .lottie file — states, transitions, interactions, and inputs — and the player executes it at runtime.

Core Workflow

  1. Define: Author your state machine in your .lottie file — states, transitions, interactions, and inputs.

  2. Load animation: Instantiate the DotLottie player with your .lottie file.

  3. Load state machine: After the animation loads, call stateMachineLoad with the state machine's ID.

  4. Start state machine: Call stateMachineStart to make it active and responsive to events.

  5. Drive inputs: Set input values or fire events from your application code to drive transitions.

  6. Stop (optional): Call stateMachineStop when interactivity is no longer needed.

State Machine Structure

State machines are JSON files stored in the s/ directory of a .lottie file. The top-level structure is:

{
  "initial": "StateName",
  "states": [],
  "interactions": [],
  "inputs": []
}
FieldRequiredDescription
initialYesName of the starting state
statesYesArray of state definitions
interactionsNoArray of interaction handlers (pointer events, animation events)
inputsNoArray of named input variables

States

Two state types are available:

PlaybackState — controls animation playback while the state is active:

PropertyRequiredTypeDescription
nameYesstringUnique identifier used to reference this state
typeYesstringMust be "PlaybackState"
animationYesstringID of the animation to play
transitionsYesarrayTransition rules that can leave this state
loopNobooleanWhether the animation loops continuously
loopCountNointegerNumber of loop iterations (minimum 1)
autoplayNobooleanWhether the animation plays immediately on entering the state
finalNobooleanIf true, no further transitions are evaluated from this state
modeNostring"Forward", "Reverse", "Bounce", or "ReverseBounce"
speedNonumberPlayback speed multiplier
segmentNostringNamed animation segment or frame range to play
backgroundColorNostringHex color applied as background while this state is active
entryActionsNoarrayActions executed when entering this state
exitActionsNoarrayActions executed when leaving this state

GlobalState — overrides behaviors across all other states:

PropertyRequiredDescription
nameYesUnique identifier
typeYesMust be "GlobalState"
transitionsYesTransitions that take precedence over state-level transitions
entryActionsNoActions executed on entering any state while the global state is active
exitActionsNoActions executed on leaving any state

Transitions

Transitions are defined inside each state's transitions array. Two types are available:

Standard transition — immediate state change:

{
  "type": "Transition",
  "toState": "NextState",
  "guards": []
}

Tweened transition — animated crossfade over a duration:

{
  "type": "Transition",
  "toState": "NextState",
  "duration": 0.4,
  "easing": [0.4, 0.0, 0.2, 1.0],
  "guards": []
}
PropertyRequired for tweenDescription
toStateYesName of the target state
guardsNoConditions that must all pass for the transition to fire
durationYesDuration of the tween in seconds
easingYesCubic Bézier control points: [x1, y1, x2, y2]

Transitions are evaluated in declaration order — the first matching transition fires. Tweened transitions block new state changes until the animation completes.

Guards

Guards are conditions on a transition that must all evaluate to true for the transition to fire.

Numeric guard:

{
  "type": "Numeric",
  "inputName": "score",
  "conditionType": "GreaterThanOrEqual",
  "compareTo": 10
}

Supported conditionType values: Equal, NotEqual, GreaterThan, GreaterThanOrEqual, LessThan, LessThanOrEqual.

String guard:

{
  "type": "String",
  "inputName": "mode",
  "conditionType": "Equal",
  "compareTo": "active"
}

Supported conditionType values: Equal, NotEqual.

Boolean guard:

{
  "type": "Boolean",
  "inputName": "isLoggedIn",
  "conditionType": "Equal",
  "compareTo": true
}

Event guard:

{
  "type": "Event",
  "inputName": "OnClick"
}

Event guards check whether the named event input has been fired. Events are edge-triggered and consumed after processing.

Interactions

Interactions respond to user or animation events and execute a list of actions. They are defined at the top level of the state machine, not inside individual states.

TypeTrigger
PointerEnterPointer enters the canvas (or specified layer)
PointerExitPointer leaves the canvas (or specified layer)
PointerDownPointer pressed down
PointerUpPointer released
PointerMovePointer moves
ClickClick on the canvas (or specified layer)
OnCompleteAnimation in a named state reaches its end
OnLoopCompleteAnimation in a named state completes one loop

Pointer-based interactions accept an optional layerName to restrict them to a specific animation layer. OnComplete and OnLoopComplete require a stateName field.

{
  "type": "PointerEnter",
  "layerName": "button_layer",
  "actions": [{ "type": "Fire", "inputName": "OnHover" }]
}

Actions

Actions execute during interactions or in a state's entryActions/exitActions. Available action types:

ActionDescription
FireFires a named event input
SetBooleanSets a boolean input to a specified value
SetNumericSets a numeric input to a specified value
SetStringSets a string input to a specified value
IncrementIncreases a numeric input by a given amount
DecrementDecreases a numeric input by a given amount
ToggleFlips a boolean input
ResetReturns an input to its initial value
SetFrameJumps the animation to a specific frame number
SetProgressSets animation progress as a value between 0 and 1
SetThemeApplies a theme by ID
OpenUrlOpens a URL — requires url and target fields
FireCustomEventSends a named custom event to the host application

Inputs

Inputs are named variables stored in the state machine. Set them at runtime to drive guard conditions.

TypeFieldsDescription
Numericname, value (number)A numeric variable
Stringname, value (string)A string variable
Booleanname, value (boolean)A boolean variable
EventnameAn edge-triggered event — no persistent value

Web Player API

Loading and Lifecycle

MethodDescription
stateMachineLoad(id: string)Loads a state machine by ID from the .lottie file. Call after the load event.
stateMachineLoadData(json: string)Loads a state machine from a raw JSON string.
stateMachineStart()Starts the loaded state machine.
stateMachineStop()Stops the active state machine.
stateMachineSetConfig(config: StateMachineConfig | null)Configures security settings, e.g. openUrlPolicy for OpenUrl actions.
import { DotLottie } from '@lottiefiles/dotlottie-web';

const dotLottie = new DotLottie({
  canvas: document.querySelector('#canvas'),
  src: 'interactive.lottie',
  autoplay: false,
});

dotLottie.addEventListener('load', () => {
  const loaded = dotLottie.stateMachineLoad('myFSM');
  if (loaded) {
    dotLottie.stateMachineStart();
  } else {
    console.error('State machine not found: myFSM');
  }
});

dotLottie.addEventListener('loadError', (err) => {
  console.error('Failed to load animation:', err);
});

Always call stateMachineLoad inside the load event handler. Calling it before the animation has loaded will fail.

State Queries

MethodReturn TypeDescription
stateMachineGetStatus()stringCurrent status of the state machine.
stateMachineGetCurrentState()stringName of the currently active state.
stateMachineGetActiveId()stringID of the currently loaded state machine.
stateMachineGet(id: string)stringState machine definition JSON by ID.
stateMachineGetListeners()string[]Names of all active listeners.
stateMachineOverrideState(state: string, immediate: boolean)booleanForces the state machine into a given state.

Input Management

MethodReturn TypeDescription
stateMachineSetBooleanInput(name, value)booleanSets a boolean input.
stateMachineSetNumericInput(name, value)booleanSets a numeric input.
stateMachineSetStringInput(name, value)booleanSets a string input.
stateMachineGetBooleanInput(name)boolean | undefinedGets the current value of a boolean input.
stateMachineGetNumericInput(name)number | undefinedGets the current value of a numeric input.
stateMachineGetStringInput(name)string | undefinedGets the current value of a string input.
stateMachineGetInputs()string[]Names of all defined inputs.
dotLottie.addEventListener('load', () => {
  dotLottie.stateMachineLoad('myFSM');
  dotLottie.stateMachineStart();

  // Set inputs before firing events to influence guard evaluation
  dotLottie.stateMachineSetNumericInput('score', 10);
  dotLottie.stateMachineSetBooleanInput('isLoggedIn', true);
  dotLottie.stateMachineSetStringInput('mode', 'active');

  const inputs = dotLottie.stateMachineGetInputs();
  console.log('Available inputs:', inputs);
});

Firing Events

MethodDescription
stateMachineFireEvent(name: string)Fires a named event input.
stateMachinePostClickEvent(x, y)Posts a click event at canvas coordinates.
stateMachinePostPointerUpEvent(x, y)Posts a pointer-up event at canvas coordinates.
stateMachinePostPointerDownEvent(x, y)Posts a pointer-down event at canvas coordinates.
stateMachinePostPointerMoveEvent(x, y)Posts a pointer-move event at canvas coordinates.
stateMachinePostPointerEnterEvent(x, y)Posts a pointer-enter event at canvas coordinates.
stateMachinePostPointerExitEvent(x, y)Posts a pointer-exit event at canvas coordinates.

Pointer interactions defined in the state machine's interactions array are handled automatically — you only need the manual Post* methods when you want to synthesize events programmatically.


State Machine Events

Listen for these events via addEventListener:

EventPayloadDescription
stateMachineStart{ type }State machine started.
stateMachineStop{ type }State machine stopped.
stateMachineTransition{ type, fromState, toState }State transition occurred.
stateMachineStateEntered{ type, state }Entered a new state.
stateMachineStateExit{ type, state }Exited a state.
stateMachineCustomEvent{ type, eventName }A FireCustomEvent action was executed.
stateMachineError{ type, error }State machine encountered an error.
stateMachineBooleanInputValueChange{ type, inputName, oldValue, newValue }A boolean input changed.
stateMachineNumericInputValueChange{ type, inputName, oldValue, newValue }A numeric input changed.
stateMachineStringInputValueChange{ type, inputName, oldValue, newValue }A string input changed.
stateMachineInputFired{ type, inputName }An event input was fired.
stateMachineInternalMessage{ type, message }Internal state machine message.
dotLottie.addEventListener('stateMachineStateEntered', (event) => {
  console.log('Entered:', event.state);
});

dotLottie.addEventListener('stateMachineTransition', (event) => {
  console.log(`${event.fromState} → ${event.toState}`);
});

dotLottie.addEventListener('stateMachineNumericInputValueChange', (event) => {
  console.log(`${event.inputName}: ${event.oldValue} → ${event.newValue}`);
});

Debugging

State machine not loading:

  • Verify the ID passed to stateMachineLoad exactly matches the state machine ID in your .lottie file.

  • Confirm stateMachineLoad is called inside the load event handler, not before it.

  • Call stateMachineGetStatus() to inspect the current status.

Transitions not firing:

  • Check that all guard conditions are met — set input values before firing the triggering event.

  • Confirm stateMachineStart() was called successfully (check its return value).

  • Add stateMachineStateEntered and stateMachineTransition listeners to trace execution.

Animation not playing in a state:

  • Verify the animation ID in your PlaybackState matches an animation ID in your .lottie file.

  • Check the segment name or frame range is valid for the referenced animation.


Last updated: April 10, 2026 at 9:12 AMEdit this page