State Machines In-Depth
In-depth guide to using State Machines in dotLottie V2 for creating interactive Lottie animations with dotlottie-js.
Advanced Features: State Machines In-Depth
State Machines, a cornerstone of the dotLottie V2 specification, transform Lottie animations into rich, interactive experiences. dotlottie-js enables bundling these interaction logics within .lottie files.
See also: Core Concepts: Managing State Machines
Understanding State Machines for Lottie Interactivity
While standard Lottie plays linearly, a State Machine introduces control logic, defining:
States: Different phases or animation segments (e.g., "Idle", "Hover", "Clicked", "Loading").
Transitions: Rules for moving between states based on events.
Events: Triggers for transitions (e.g., "onClick", "onMouseEnter", "onComplete", custom events).
Actions: Things to do upon entering/exiting states (e.g., play animation, set loop mode, dispatch custom event).
dotlottie-js Role: Similar to theming, dotlottie-js packages the State Machine JSON data according to the specification. It does not execute the state machine logic. The dotLottie player reads this data and manages the interactive behavior at runtime.
The State Machine JSON Schema
The structure of the state machine data is defined by the official dotLottie specification. It's crucial to adhere to this schema.
Key Components (Refer to dotlottie.io/docs/state-machines for the full specification):
descriptor: Contains the state machine'sidand theinitialstate ID.states: An object where keys are state IDs.Each state object defines:
animationId: (Optional) The ID of the Lottie animation to play in this state (must match an animation added viaaddAnimation()).segment: (Optional) A specific frame segment[start, end]of the animation to play.speed: (Optional) Playback speed multiplier.loop: (Optional) Number of times to loop, ortruefor infinite.autoplay: (Optional) Whether to start playing immediately upon entering the state.on: (Optional) An array of listeners defining transitions out of this state.Each listener has
event(e.g., "onClick", "onMouseEnter", "onComplete", "customEventName") andtransitionTo(the target state ID).
entryActions/exitActions: (Optional) Actions to perform on state entry/exit.
// Simplified Conceptual Example
{
"descriptor": {
"id": "button_interaction",
"initial": "idle"
},
"states": {
"idle": {
"animationId": "anim_idle",
"loop": true,
"autoplay": true,
"on": [
{ "event": "onMouseEnter", "transitionTo": "hover" },
{ "event": "onClick", "transitionTo": "pressed" }
]
},
"hover": {
"animationId": "anim_hover",
"loop": true,
"autoplay": true,
"on": [
{ "event": "onMouseLeave", "transitionTo": "idle" },
{ "event": "onClick", "transitionTo": "pressed" }
]
},
"pressed": {
"animationId": "anim_press",
"autoplay": true,
"on": [
{ "event": "onComplete", "transitionTo": "idle" } // Go back to idle after press animation finishes
]
}
}
}Important: Writing correct State Machine JSON requires careful planning of your interaction logic and adherence to the spec.
Packaging State Machines with dotlottie-js
Use methods on the DotLottie instance:
addStateMachine({ id, data, name }): Adds the state machine definition.idmust be unique.datais the State Machine JSON object. SeeaddStateMachine().Add Animations: Ensure all animations referenced by
animationIdin the state machine data are added viaaddAnimation().await dotlottie.build(): Finalizes the package, writing state machine data tostates/<state_machine_id>.jsonand updating the manifest. Seebuild().
import { DotLottie } from "@dotlottie/dotlottie-js";
async function packageStateMachine() {
const dotlottie = new DotLottie();
// 1. Add Animations (ensure IDs match those in state machine data)
await dotlottie.addAnimation({ id: "anim_idle", data: idleLottieJson });
await dotlottie.addAnimation({ id: "anim_hover", data: hoverLottieJson });
await dotlottie.addAnimation({ id: "anim_press", data: pressLottieJson });
// 2. Define State Machine Data (using the example structure from above)
const stateMachineData = {
descriptor: { id: "button_interaction", initial: "idle" },
states: {
idle: {
animationId: "anim_idle",
loop: true,
autoplay: true,
on: [
{ event: "onMouseEnter", transitionTo: "hover" },
{ event: "onClick", transitionTo: "pressed" },
],
},
hover: {
animationId: "anim_hover",
loop: true,
autoplay: true,
on: [
{ event: "onMouseLeave", transitionTo: "idle" },
{ event: "onClick", transitionTo: "pressed" },
],
},
pressed: {
animationId: "anim_press",
autoplay: true,
on: [{ event: "onComplete", transitionTo: "idle" }],
},
},
};
// 3. Add the State Machine
dotlottie.addStateMachine({
id: "sm_button", // ID for the manifest
data: stateMachineData,
name: "Button Interaction Logic",
});
// 4. Build
await dotlottie.build();
// 5. Export
// const buffer = await dotlottie.toArrayBuffer();
console.log("Created .lottie with state machine.");
}
// packageStateMachine();How Players Use State Machines
The dotLottie player:
Loads the
.lottieand reads the manifest.Identifies available state machines.
Listens for defined events (e.g., clicks, hovers on the player element).
Manages the current state based on transitions.
Controls the playback (play, pause, loop, segment) of the associated Lottie animation according to the current state's definition.
May provide APIs to
triggerStateMachineEvent('customEvent')orsetStateMachineState('specificState').
Use Cases for State Machines
Interactive Buttons/Toggles: Hover effects, click animations, disabled states.
Character Controls: Make a character walk, jump, or react to clicks.
Simple Games: Control game states (Start, Playing, Game Over).
Onboarding Flows: Guide users through steps with interactive Lottie elements.
Loading Indicators: Show different animations for loading, success, error states.
By bundling state machines, dotlottie-js helps create powerful, self-contained interactive Lottie experiences.
Next up: API Overview