-
Notifications
You must be signed in to change notification settings - Fork 31
State Machines
This guide shows you how to create interactive dotLottie animations using the @lottiefiles/dotlottie-web package. Learn to build rich, interactive experiences with user inputs, animation controls, and dynamic behaviors.
Interactive dotLottie animations use state machines to:
- Control animation playback based on user interactions
- Switch between different animations dynamically
- Create complex interactive behaviors
- Respond to events like clicks, hovers, and custom inputs
- Build stateful animations that remember user interactions
📖 Learn More About State Machines
For detailed information about dotLottie state machine specifications, visit the official dotLottie spec.
import { DotLottie } from '@lottiefiles/dotlottie-web';
const canvas = document.getElementById('canvas');
const dotLottie = new DotLottie({
canvas,
src: 'path/to/interactive-animation.lottie', // Contains state machine
autoplay: true,
loop: true,
stateMachineConfig: {
openUrlPolicy: {
requireUserInteraction: true,
whitelist: ['https://trusted-site.com']
}
}
});// Wait for animation to load before starting state machine
dotLottie.addEventListener('load', () => {
// Load a state machine by ID (defined in the .lottie file)
dotLottie.stateMachineLoad('my-state-machine-id');
// Start the state machine
dotLottie.stateMachineStart();
// Check if it's running
console.log(dotLottie.stateMachineGetStatus()); // "Playing" or "Stopped"
});// Configure security policy (can be set at creation or runtime)
dotLottie.stateMachineSetConfig({
openUrlPolicy: {
requireUserInteraction: true, // Require user action before opening URLs
whitelist: ['*.lottiefiles.com/*', 'https://myapp.com'] // Allowed URL patterns
}
});
// Load and start
dotLottie.stateMachineLoad('button-interaction');
dotLottie.stateMachineStart();
// Stop and check status
dotLottie.stateMachineStop();
console.log(dotLottie.stateMachineGetStatus()); // "Stopped"
// Get current state name
console.log(dotLottie.stateMachineGetCurrentState()); // "idle"
// Override current state (force transition)
dotLottie.stateMachineOverrideState('active', true); // immediate: trueState machines use inputs to store and modify values that control behavior:
// Set input values
dotLottie.stateMachineSetBooleanInput('isPressed', true);
dotLottie.stateMachineSetNumericInput('counter', 5);
dotLottie.stateMachineSetStringInput('username', 'john');
// Get input values
const isPressed = dotLottie.stateMachineGetBooleanInput('isPressed');
const counter = dotLottie.stateMachineGetNumericInput('counter');
const username = dotLottie.stateMachineGetStringInput('username');
// Fire events (trigger event inputs)
dotLottie.stateMachineFireEvent('button_clicked');
dotLottie.stateMachineFireEvent('animation_complete');Important: You don't need to manually handle pointer events! The dotLottie-web library automatically:
- Detects required events from your state machine interactions
- Automatically adds event listeners to the canvas
- Handles coordinate conversion and posts events to the state machine
When you call dotLottie.stateMachineStart(), the library:
- Calls
stateMachineGetListeners()to see what events your state machine needs - Automatically adds the appropriate event listeners (
click,pointerdown,pointerup, etc.) - Handles all coordinate calculations and event posting internally
// This is all you need - no manual event handling required!
dotLottie.addEventListener("load", () => {
dotLottie.stateMachineLoadData(JSON.stringify(stateMachine));
dotLottie.stateMachineStart(); // Events are automatically handled after this
});// Listen for state changes
dotLottie.addEventListener('stateMachineStateEntered', (event) => {
console.log('Entered state:', event.state);
});
dotLottie.addEventListener('stateMachineStateExit', (event) => {
console.log('Exited state:', event.state);
});
// Listen for custom events from the state machine
dotLottie.addEventListener('stateMachineCustomEvent', (event) => {
console.log('Custom event:', event.eventName);
// Example: Handle different custom events
switch (event.eventName) {
case 'button_clicked':
showNotification('Button was clicked!');
break;
case 'animation_complete':
triggerNextStep();
break;
}
});
// Listen for input value changes
dotLottie.addEventListener('stateMachineNumericInputValueChange', (event) => {
console.log(`Input ${event.inputName} changed from ${event.oldValue} to ${event.newValue}`);
});Simple click interaction that plays an animation on user interaction:
const canvas = document.getElementById('dotLottieCanvas');
const dotLottie = new DotLottie({
canvas,
src: 'https://lottie.host/fba88936-b753-4751-a6ca-94db246157cf/5pGajCeC0B.json'
});
const clickMachine = {
initial: "Idle",
states: [
{
name: "Idle",
type: "GlobalState",
transitions: [
{
type: "Transition",
toState: "PlayAnimation",
guards: [
{
type: "Event",
inputName: "onClick"
}
]
}
]
},
{
name: "PlayAnimation",
type: "PlaybackState",
animation: "",
mode: "Forward",
autoplay: true,
transitions: []
}
],
interactions: [
{
type: "Click",
actions: [
{
type: "Fire",
inputName: "onClick"
}
]
}
],
inputs: [
{
type: "Event",
name: "onClick"
}
]
};
dotLottie.addEventListener("load", () => {
dotLottie.stateMachineLoadData(JSON.stringify(clickMachine));
dotLottie.stateMachineStart();
});Create smooth hover animations with forward and reverse playback:
const canvas = document.getElementById('dotLottieCanvas');
const dotLottie = new DotLottie({
canvas,
src: 'https://lottie.host/b3db2fe4-76ca-4628-946f-fab26eee90b3/vzUiccejvT.lottie'
});
const hoverMachine = {
initial: "idle",
states: [
{
// Global state waiting for cursor events
type: "GlobalState",
name: "idle",
transitions: [
{
type: "Transition",
toState: "hoverIn",
guards: [{ type: "Event", inputName: "pointerEnter" }]
},
{
type: "Transition",
toState: "hoverOut",
guards: [{ type: "Event", inputName: "pointerExit" }]
}
]
},
// Play forward on hover in
{
animation: "",
type: "PlaybackState",
name: "hoverIn",
mode: "Forward",
autoplay: true,
transitions: []
},
// Play in reverse on hover out
{
animation: "",
type: "PlaybackState",
name: "hoverOut",
mode: "Reverse",
autoplay: true,
transitions: []
}
],
interactions: [
{
type: "PointerEnter",
actions: [{ type: "Fire", inputName: "pointerEnter" }]
},
{
type: "PointerExit",
actions: [{ type: "Fire", inputName: "pointerExit" }]
}
],
inputs: [
{ type: "Event", name: "pointerEnter" },
{ type: "Event", name: "pointerExit" }
]
};
dotLottie.addEventListener("load", () => {
dotLottie.stateMachineLoadData(JSON.stringify(hoverMachine));
dotLottie.stateMachineStart();
});Press and hold interaction with forward/reverse animation:
const canvas = document.getElementById('dotLottieCanvas');
const dotLottie = new DotLottie({
canvas,
src: 'https://lottie.host/cb480e3f-1db1-4fb9-a812-592cd1aaef3a/Qda343MSSf.lottie'
});
const holdMachine = {
initial: "Idle",
states: [
{
name: "Idle",
type: "GlobalState",
transitions: [
{
type: "Transition",
toState: "HoldForward",
guards: [
{
type: "Event",
inputName: "onHoldStart"
}
]
},
{
type: "Transition",
toState: "HoldReverse",
guards: [
{
type: "Event",
inputName: "onHoldEnd"
}
]
}
]
},
{
name: "HoldForward",
type: "PlaybackState",
animation: "",
autoplay: true,
mode: "Forward",
transitions: []
},
{
name: "HoldReverse",
type: "PlaybackState",
animation: "",
autoplay: true,
mode: "Reverse",
transitions: []
}
],
interactions: [
{
type: "PointerDown",
actions: [
{
type: "Fire",
inputName: "onHoldStart"
}
]
},
{
type: "PointerUp",
actions: [
{
type: "Fire",
inputName: "onHoldEnd"
}
]
}
],
inputs: [
{
type: "Event",
name: "onHoldStart"
},
{
type: "Event",
name: "onHoldEnd"
}
]
};
dotLottie.addEventListener("load", () => {
dotLottie.stateMachineLoadData(JSON.stringify(holdMachine));
dotLottie.stateMachineStart();
});Animation controlled by cursor position across the screen:
const canvas = document.getElementById('dotLottieCanvas');
const dotLottie = new DotLottie({
canvas,
src: 'https://lottie.host/fba88936-b753-4751-a6ca-94db246157cf/5pGajCeC0B.json'
});
const cursorMachine = {
initial: "CursorControlled",
states: [
{
name: "CursorControlled",
type: "PlaybackState",
animation: "",
entryActions: [
{
type: "SetFrame",
value: "$cursorFrame"
}
],
transitions: [
{
type: "Transition",
toState: "CursorControlled",
guards: [
{
type: "Event",
inputName: "cursorMoved"
}
]
}
]
}
],
interactions: [],
inputs: [
{
type: "Numeric",
name: "cursorFrame",
value: 0
},
{
type: "Event",
name: "cursorMoved"
}
]
};
dotLottie.addEventListener("load", () => {
dotLottie.stateMachineLoadData(JSON.stringify(cursorMachine));
dotLottie.stateMachineStart();
const syncToCursor = (event) => {
const pos = Math.min(event.clientX / document.body.clientWidth, 1);
const frame = dotLottie.totalFrames * pos;
dotLottie.stateMachineSetNumericInput("cursorFrame", frame);
dotLottie.stateMachineFireEvent("cursorMoved");
};
window.addEventListener("mousemove", syncToCursor);
});Animation synchronized with page scroll position:
const canvas = document.getElementById('dotLottieCanvas');
const dotLottie = new DotLottie({
canvas,
src: 'https://lottie.host/fba88936-b753-4751-a6ca-94db246157cf/5pGajCeC0B.json'
});
const scrollMachine = {
initial: "SyncProgress",
states: [
{
name: "SyncProgress",
type: "PlaybackState",
animation: "",
entryActions: [
{
type: "SetProgress",
value: "$scrollProgress"
}
],
transitions: [
{
type: "Transition",
toState: "SyncProgress",
guards: [
{
type: "Event",
inputName: "updateScroll"
}
]
}
]
}
],
interactions: [],
inputs: [
{
type: "Numeric",
name: "scrollProgress",
value: 0
},
{
type: "Event",
name: "updateScroll"
}
]
};
dotLottie.addEventListener("load", () => {
dotLottie.stateMachineLoadData(JSON.stringify(scrollMachine));
dotLottie.stateMachineStart();
const syncToScroll = () => {
const scrollTop = window.scrollY;
const scrollHeight = document.body.scrollHeight - window.innerHeight;
const scrollProgress = Math.min(scrollTop / scrollHeight, 1) * 100;
dotLottie.stateMachineSetNumericInput("scrollProgress", scrollProgress);
dotLottie.stateMachineFireEvent("updateScroll");
};
window.addEventListener("scroll", syncToScroll);
});Automatic theme switching with completion events:
const canvas = document.getElementById('dotLottieCanvas');
const dotLottie = new DotLottie({
canvas,
src: 'https://lottie.host/8e34d211-e22e-459e-bfc7-7400b283be87/6RKEZ9wCqO.lottie'
});
const themeMachine = {
initial: "Main",
inputs: [{ type: "Numeric", name: "themeIndex", value: 0 }],
states: [
{
name: "Main",
type: "PlaybackState",
animation: "",
autoplay: true,
transitions: [
{
type: "Transition",
toState: "ApplyWater",
guards: [
{
type: "Numeric",
inputName: "themeIndex",
conditionType: "Equal",
compareTo: 1
}
]
}
]
},
{
name: "ApplyWater",
type: "PlaybackState",
animation: "",
autoplay: true,
entryActions: [{ type: "SetTheme", value: "Water" }],
transitions: [
{
type: "Transition",
toState: "ApplyAir",
guards: [
{
type: "Numeric",
inputName: "themeIndex",
conditionType: "Equal",
compareTo: 2
}
]
}
]
},
{
name: "ApplyAir",
type: "PlaybackState",
animation: "",
autoplay: true,
entryActions: [{ type: "SetTheme", value: "air" }],
transitions: [
{
type: "Transition",
toState: "ApplyEarth",
guards: [
{
type: "Numeric",
inputName: "themeIndex",
conditionType: "Equal",
compareTo: 3
}
]
}
]
},
{
name: "ApplyEarth",
type: "PlaybackState",
animation: "",
autoplay: true,
entryActions: [{ type: "SetTheme", value: "earth" }],
transitions: [
{
type: "Transition",
toState: "Main",
guards: [
{
type: "Numeric",
inputName: "themeIndex",
conditionType: "Equal",
compareTo: 0
}
]
}
]
}
],
interactions: [
{
type: "OnComplete",
stateName: "Main",
actions: [{ type: "SetNumeric", inputName: "themeIndex", value: 1 }]
},
{
type: "OnComplete",
stateName: "ApplyWater",
actions: [{ type: "SetNumeric", inputName: "themeIndex", value: 2 }]
},
{
type: "OnComplete",
stateName: "ApplyAir",
actions: [{ type: "SetNumeric", inputName: "themeIndex", value: 3 }]
},
{
type: "OnComplete",
stateName: "ApplyEarth",
actions: [{ type: "SetNumeric", inputName: "themeIndex", value: 0 }]
}
]
};
dotLottie.addEventListener("load", () => {
dotLottie.stateMachineLoadData(JSON.stringify(themeMachine));
dotLottie.stateMachineStart();
});Smooth transitions between different animation segments using tweened transitions:
const canvas = document.getElementById('dotLottieCanvas');
const dotLottie = new DotLottie({
canvas,
src: 'https://lottie.host/1f21c068-194f-45cc-9003-f587ad559ba2/opL6U2S624.lottie'
});
const ratingMachine = {
initial: "laughing",
states: [
{
name: "global",
type: "GlobalState",
animation: "",
transitions: [
{
type: "Tweened",
toState: "angry",
duration: 0.5,
easing: [0.76, 0, 0.24, 1],
guards: [
{
type: "Numeric",
conditionType: "Equal",
inputName: "rating",
compareTo: 1
}
]
},
{
type: "Tweened",
toState: "sad",
duration: 0.5,
easing: [0.76, 0, 0.24, 1],
guards: [
{
type: "Numeric",
conditionType: "Equal",
inputName: "rating",
compareTo: 2
}
]
},
{
type: "Tweened",
toState: "mourn",
duration: 0.5,
easing: [0.76, 0, 0.24, 1],
guards: [
{
type: "Numeric",
conditionType: "Equal",
inputName: "rating",
compareTo: 3
}
]
},
{
type: "Tweened",
toState: "wink",
duration: 0.5,
easing: [0.76, 0, 0.24, 1],
guards: [
{
type: "Numeric",
conditionType: "Equal",
inputName: "rating",
compareTo: 4
}
]
},
{
type: "Tweened",
toState: "laughing",
duration: 0.5,
easing: [0.76, 0, 0.24, 1],
guards: [
{
type: "Numeric",
conditionType: "Equal",
inputName: "rating",
compareTo: 5
}
]
}
]
},
{
type: "PlaybackState",
name: "angry",
animation: "",
autoplay: true,
loop: true,
segment: "angry",
transitions: []
},
{
type: "PlaybackState",
name: "sad",
animation: "",
autoplay: true,
loop: true,
segment: "sad",
transitions: []
},
{
type: "PlaybackState",
name: "mourn",
animation: "",
autoplay: true,
loop: true,
segment: "mourn",
transitions: []
},
{
type: "PlaybackState",
name: "wink",
animation: "",
autoplay: true,
loop: true,
segment: "wink",
transitions: []
},
{
type: "PlaybackState",
name: "laughing",
animation: "",
autoplay: true,
loop: true,
segment: "laughing",
transitions: []
}
],
inputs: [
{
type: "Numeric",
name: "rating",
value: 5 // Start with laughing
}
],
interactions: [
{
type: "PointerDown",
layerName: "angry",
actions: [
{
type: "SetNumeric",
inputName: "rating",
value: 1
}
]
},
{
type: "PointerDown",
layerName: "sad",
actions: [
{
type: "SetNumeric",
inputName: "rating",
value: 2
}
]
},
{
type: "PointerDown",
layerName: "mourn",
actions: [
{
type: "SetNumeric",
inputName: "rating",
value: 3
}
]
},
{
type: "PointerDown",
layerName: "wink",
actions: [
{
type: "SetNumeric",
inputName: "rating",
value: 4
}
]
},
{
type: "PointerDown",
layerName: "laughing",
actions: [
{
type: "SetNumeric",
inputName: "rating",
value: 5
}
]
}
]
};
dotLottie.addEventListener("load", () => {
dotLottie.stateMachineLoadData(JSON.stringify(ratingMachine));
dotLottie.stateMachineStart();
});Animation that responds to microphone input:
const canvas = document.getElementById('dotLottieCanvas');
const dotLottie = new DotLottie({
canvas,
src: 'https://lottie.host/fba88936-b753-4751-a6ca-94db246157cf/5pGajCeC0B.json'
});
const audioMachine = {
initial: "VolumeControlled",
inputs: [
{ type: "Numeric", name: "volumeLevel", value: 0 },
{ type: "Event", name: "volumeChanged" }
],
states: [
{
name: "VolumeControlled",
type: "PlaybackState",
animation: "",
entryActions: [
{
type: "SetProgress",
value: "$volumeLevel"
}
],
transitions: [
{
type: "Transition",
toState: "VolumeControlled",
guards: [{ type: "Event", inputName: "volumeChanged" }]
}
]
}
],
interactions: []
};
const audioSensitivity = 0.4; // Adjust sensitivity
dotLottie.addEventListener("load", async () => {
dotLottie.stateMachineLoadData(JSON.stringify(audioMachine));
dotLottie.stateMachineStart();
try {
const audioCtx = new AudioContext();
const analyser = new AnalyserNode(audioCtx, {
fftSize: 64,
maxDecibels: -25,
minDecibels: -60,
smoothingTimeConstant: 0.6
});
const data = new Uint8Array(analyser.frequencyBinCount);
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const source = audioCtx.createMediaStreamSource(stream);
source.connect(analyser);
function updateFromMic() {
analyser.getByteFrequencyData(data);
let volumeRaw = data[0]; // 0–255 from mic
let volume = volumeRaw * audioSensitivity;
volume = Math.max(0, Math.min(100, volume)); // Clamp to 0–100
dotLottie.stateMachineSetNumericInput("volumeLevel", volume);
dotLottie.stateMachineFireEvent("volumeChanged");
requestAnimationFrame(updateFromMic);
}
await audioCtx.resume();
requestAnimationFrame(updateFromMic);
} catch (error) {
console.error('Microphone access denied:', error);
}
});📁 View on CodePen (Android mobile only)
Animation controlled by device tilt (mobile devices):
const canvas = document.getElementById('dotLottieCanvas');
const enableBtn = document.getElementById('enableOrientation');
const dotLottie = new DotLottie({
canvas,
src: 'https://lottie.host/fba88936-b753-4751-a6ca-94db246157cf/5pGajCeC0B.json'
});
const orientationMachine = {
initial: "OrientationControlled",
inputs: [
{
type: "Numeric",
name: "tiltProgress",
value: 0
},
{
type: "Event",
name: "orientationChanged"
}
],
states: [
{
name: "OrientationControlled",
type: "PlaybackState",
animation: "",
entryActions: [
{
type: "SetProgress",
value: "$tiltProgress"
}
],
transitions: [
{
type: "Transition",
toState: "OrientationControlled",
guards: [{ type: "Event", inputName: "orientationChanged" }]
}
]
}
],
interactions: []
};
function handleOrientation(event) {
const gamma = Math.max(-90, Math.min(90, event.gamma || 0));
const percent = ((gamma + 90) / 180) * 100;
dotLottie.stateMachineSetNumericInput("tiltProgress", percent);
dotLottie.stateMachineFireEvent("orientationChanged");
}
dotLottie.addEventListener("load", async () => {
dotLottie.stateMachineLoadData(JSON.stringify(orientationMachine));
dotLottie.stateMachineStart();
if (
typeof DeviceOrientationEvent !== "undefined" &&
typeof DeviceOrientationEvent.requestPermission === "function"
) {
// iOS 13+ Safari requires user interaction
enableBtn.style.display = "block";
} else if ("DeviceOrientationEvent" in window) {
// Orientation is supported without permission
window.addEventListener("deviceorientation", handleOrientation);
}
});
enableBtn.addEventListener("click", async () => {
const granted = await DeviceOrientationEvent.requestPermission();
if (granted === "granted") {
window.addEventListener("deviceorientation", handleOrientation);
enableBtn.style.display = "none";
} else {
alert("Motion access was denied.");
}
});import { DotLottieReact } from '@lottiefiles/dotlottie-react';
import { useRef, useState } from 'react';
function InteractiveAnimation() {
const dotLottieRef = useRef(null);
const [currentState, setCurrentState] = useState('idle');
const [counter, setCounter] = useState(0);
const handleLoad = () => {
const dotLottie = dotLottieRef.current;
if (!dotLottie) return;
// Load and start state machine after animation loads
dotLottie.stateMachineLoad('interactive');
dotLottie.stateMachineStart();
// Listen for state changes
const handleStateChange = (event) => {
setCurrentState(event.state);
};
const handleCounterChange = (event) => {
if (event.inputName === 'counter') {
setCounter(event.newValue);
}
};
dotLottie.addEventListener('stateMachineStateEntered', handleStateChange);
dotLottie.addEventListener('stateMachineNumericInputValueChange', handleCounterChange);
};
const handleIncrement = () => {
const dotLottie = dotLottieRef.current;
if (dotLottie) {
const currentValue = dotLottie.stateMachineGetNumericInput('counter') || 0;
dotLottie.stateMachineSetNumericInput('counter', currentValue + 1);
dotLottie.stateMachineFireEvent('counter_changed');
}
};
const handleReset = () => {
const dotLottie = dotLottieRef.current;
if (dotLottie) {
dotLottie.stateMachineSetNumericInput('counter', 0);
dotLottie.stateMachineFireEvent('reset');
}
};
return (
<div>
<DotLottieReact
ref={dotLottieRef}
src="interactive-counter.lottie"
loop
autoplay
onLoad={handleLoad}
style={{ width: 400, height: 400 }}
/>
<div>
<p>Current State: {currentState}</p>
<p>Counter: {counter}</p>
<button onClick={handleIncrement}>Increment</button>
<button onClick={handleReset}>Reset</button>
</div>
</div>
);
}<template>
<div>
<DotLottieVue
ref="dotLottieRef"
:src="animationSrc"
:loop="true"
:autoplay="true"
@load="onLoad"
style="width: 400px; height: 400px"
/>
<div>
<p>Current State: {{ currentState }}</p>
<button @click="toggleState">Toggle</button>
<button @click="setCustomInput">Set Custom Value</button>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { DotLottieVue } from '@lottiefiles/dotlottie-vue';
const dotLottieRef = ref(null);
const animationSrc = ref('interactive-toggle.lottie');
const currentState = ref('idle');
const onLoad = () => {
const dotLottie = dotLottieRef.value?.getDotLottieInstance();
if (!dotLottie) return;
// Load state machine
dotLottie.stateMachineLoad('toggle');
dotLottie.stateMachineStart();
// Listen for events
dotLottie.addEventListener('stateMachineStateEntered', (event) => {
currentState.value = event.state;
});
};
const toggleState = () => {
const dotLottie = dotLottieRef.value?.getDotLottieInstance();
if (dotLottie) {
dotLottie.stateMachineFireEvent('toggle');
}
};
const setCustomInput = () => {
const dotLottie = dotLottieRef.value?.getDotLottieInstance();
if (dotLottie) {
dotLottie.stateMachineSetStringInput('user_input', 'Hello World');
dotLottie.stateMachineFireEvent('input_changed');
}
};
</script>// Loading and lifecycle
dotLottie.stateMachineLoad(stateMachineId: string): boolean
dotLottie.stateMachineStart(): boolean
dotLottie.stateMachineStop(): boolean
// Configuration
dotLottie.stateMachineSetConfig(config: StateMachineConfig | null): void
// Status and information
dotLottie.stateMachineGetStatus(): string
dotLottie.stateMachineGetCurrentState(): string
dotLottie.stateMachineGetActiveId(): string
// State control
dotLottie.stateMachineOverrideState(state: string, immediate: boolean): booleaninterface StateMachineConfig {
openUrlPolicy?: {
requireUserInteraction?: boolean; // Default: true
whitelist?: string[]; // Default: [] (blocks all URLs)
};
}OpenURL Policy Controls:
-
requireUserInteraction: Whentrue, URLs only open after user actions (clicks, etc.) -
whitelist: Array of allowed URL patterns. Supports wildcards (*), empty array blocks all URLs
URL Pattern Examples:
// Security configurations
const configs = {
// Block all URLs
strict: { openUrlPolicy: { whitelist: [] } },
// Allow specific domains
selective: {
openUrlPolicy: {
whitelist: ['https://myapp.com', '*.lottiefiles.com/*']
}
},
// Development (less secure)
permissive: {
openUrlPolicy: {
requireUserInteraction: false,
whitelist: ['*']
}
}
};// Set input values
dotLottie.stateMachineSetBooleanInput(name: string, value: boolean): boolean
dotLottie.stateMachineSetNumericInput(name: string, value: number): boolean
dotLottie.stateMachineSetStringInput(name: string, value: string): boolean
// Get input values
dotLottie.stateMachineGetBooleanInput(name: string): boolean | undefined
dotLottie.stateMachineGetNumericInput(name: string): number | undefined
dotLottie.stateMachineGetStringInput(name: string): string | undefined
// Fire events
dotLottie.stateMachineFireEvent(name: string): void// State machine events
dotLottie.addEventListener('stateMachineStateEntered', callback)
dotLottie.addEventListener('stateMachineStateExit', callback)
dotLottie.addEventListener('stateMachineTransition', callback)
// Input change events
dotLottie.addEventListener('stateMachineNumericInputValueChange', callback)
dotLottie.addEventListener('stateMachineStringInputValueChange', callback)
dotLottie.addEventListener('stateMachineBooleanInputValueChange', callback)
// Custom and error events
dotLottie.addEventListener('stateMachineCustomEvent', callback)
dotLottie.addEventListener('stateMachineError', callback)The examples in this guide load state machines externally for demonstration purposes. In production, you can embed state machines directly into .lottie files using the @dotlottie/dotlottie-js SDK:
import { DotLottie } from '@dotlottie/dotlottie-js';
async function createDotLottieWithStateMachine() {
try {
const dotlottie = new DotLottie();
// Add your animation
dotlottie.addAnimation({
id: 'my-animation',
url: 'https://assets.lottiefiles.com/packages/lf20_VeqS4d.json',
name: 'Interactive Animation'
});
// Add your state machine
dotlottie.addStateMachine({
id: 'my-state-machine',
data: clickMachine // Use your state machine JSON here
});
// Build the .lottie file
await dotlottie.build();
// Export to ArrayBuffer
const arrayBuffer = await dotlottie.toArrayBuffer();
return arrayBuffer;
} catch (error) {
console.error('Error creating .lottie file:', error);
}
}
// Usage
const buffer = await createDotLottieWithStateMachine();