-
Notifications
You must be signed in to change notification settings - Fork 25
dotLottie State Machine Guide
⚠️ Experimental Feature
Interactive animations and state machines are experimental features in dotLottie. APIs may change in future versions. Use with caution in production environments.
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: true
State 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.data.state);
});
dotLottie.addEventListener('stateMachineStateExit', (event) => {
console.log('Exited state:', event.data.state);
});
// Listen for custom events from the state machine
dotLottie.addEventListener('stateMachineCustomEvent', (event) => {
console.log('Custom event:', event.data.value);
// Example: Handle different custom events
switch (event.data.value) {
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.data.inputName} changed to ${event.data.value}`);
});
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.data.state);
};
const handleCounterChange = (event) => {
if (event.data.inputName === 'counter') {
setCounter(event.data.value);
}
};
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.data.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): boolean
interface 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();