FasterMotion
API ReferenceFmtion Format

Lottie Animations

After Effects animations with scroll sync, state machines, and mouse tracking

Lottie animations in .fmtion files support After Effects animations exported with Bodymovin. They can be scroll-synced, have state machines, and respond to mouse tracking.

Basic Lottie

{
  "lottie": [
    {
      "id": "hero-animation",
      "container": "#hero-lottie",
      "src": "/animations/hero.json",
      "renderer": "svg",
      "autoplay": true,
      "loop": true,
      "speed": 1
    }
  ]
}

LottieAnimation Fields

FieldTypeRequiredDescription
idstringYesUnique animation ID
containerstringYesCSS selector for container
srcstringYesURL to .json Lottie file
renderer'svg' | 'canvas' | 'html'NoRenderer type (default: 'svg')
autoplaybooleanNoAuto-play on load
loopbooleanNoLoop animation
speednumberNoPlayback speed (1 = normal)
scrollLottieScrollConfigNoScroll sync configuration
statesRecord<string, LottieStateDefinition>NoState definitions
transitionsLottieTransitionDefinition[]NoState transitions
initialstringNoInitial state name
mouseTrackingLottieMouseTrackingConfigNoMouse tracking config

Renderer Types

RendererDescriptionBest For
svgSVG renderingCrisp scaling, small animations
canvasCanvas 2D renderingComplex animations, performance
htmlDOM renderingInteractivity, accessibility

Scroll-Synced Lottie

Scrub Lottie animation based on scroll position:

{
  "lottie": [
    {
      "id": "scroll-story",
      "container": "#scroll-lottie",
      "src": "/animations/scroll-story.json",
      "scroll": {
        "trigger": ".scroll-section",
        "start": "top center",
        "end": "bottom center",
        "scrub": true
      }
    }
  ]
}

Scroll Configuration

interface LottieScrollConfig {
  trigger?: string;        // Trigger element selector
  start?: string;          // Start position
  end?: string;            // End position
  scrub?: boolean | number; // Scrub (true or smoothing factor)
  controlsState?: string;  // State to control via scroll
  pin?: boolean;           // Pin element during scroll
  pinSpacing?: boolean;    // Add spacing for pin
  markers?: boolean;       // Show debug markers
}

Position Syntax

Same as scroll bindings: "{element edge} {viewport position}"

{
  "scroll": {
    "trigger": ".hero",
    "start": "top top",      // When hero top reaches viewport top
    "end": "bottom center",  // When hero bottom reaches viewport center
    "scrub": 0.5             // Smooth scrubbing
  }
}

Pinned Scroll Animation

{
  "lottie": [
    {
      "id": "pinned-animation",
      "container": "#pinned-lottie",
      "src": "/animations/sequence.json",
      "scroll": {
        "trigger": ".pinned-section",
        "start": "top top",
        "end": "+=200%",
        "scrub": true,
        "pin": true,
        "pinSpacing": true
      }
    }
  ]
}

State Machine

Define named states with frame segments and transitions:

{
  "lottie": [
    {
      "id": "interactive-button",
      "container": "#button-lottie",
      "src": "/animations/button.json",
      "initial": "idle",
      "states": {
        "idle": {
          "segment": [0, 30],
          "loop": true
        },
        "hover": {
          "segment": [31, 60],
          "loop": false
        },
        "pressed": {
          "segment": [61, 90],
          "loop": false
        },
        "success": {
          "segment": [91, 120],
          "loop": false,
          "speed": 1.5
        }
      },
      "transitions": [
        { "from": "idle", "to": "hover", "on": "mouseenter" },
        { "from": "hover", "to": "idle", "on": "mouseleave" },
        { "from": "hover", "to": "pressed", "on": "mousedown" },
        { "from": "pressed", "to": "hover", "on": "mouseup" },
        { "from": "pressed", "to": "success", "on": "click" },
        { "from": "success", "to": "idle", "on": "complete" }
      ]
    }
  ]
}

State Definition

interface LottieStateDefinition {
  segment?: [number, number]; // Frame segment [start, end]
  loop?: boolean;             // Loop this state
  reverse?: boolean;          // Play in reverse
  speed?: number;             // Playback speed
}

Transition Definition

interface LottieTransitionDefinition {
  from: string;      // Source state ('*' for any)
  to: string;        // Target state
  on?: string;       // Event that triggers transition
  condition?: string; // Condition expression
  duration?: number;  // Blend duration in ms
}

Transition Events

EventDescription
mouseenterMouse enters container
mouseleaveMouse leaves container
mousedownMouse button pressed
mouseupMouse button released
clickClick on container
completeAnimation segment completed

Any State Transitions

Use "*" for transitions from any state:

{
  "transitions": [
    { "from": "*", "to": "error", "on": "error-event" },
    { "from": "*", "to": "idle", "on": "reset" }
  ]
}

Conditional Transitions

{
  "transitions": [
    {
      "from": "idle",
      "to": "premium",
      "on": "click",
      "condition": "user/isPremium == true"
    }
  ]
}

Scroll-Controlled States

Use scroll position to control which state is active:

{
  "lottie": [
    {
      "id": "scroll-states",
      "container": "#scroll-states-lottie",
      "src": "/animations/journey.json",
      "initial": "step1",
      "states": {
        "step1": { "segment": [0, 60] },
        "step2": { "segment": [60, 120] },
        "step3": { "segment": [120, 180] }
      },
      "scroll": {
        "trigger": ".journey-section",
        "start": "top top",
        "end": "bottom top",
        "controlsState": "step1"
      }
    }
  ]
}

Mouse Tracking

Make Lottie animations follow mouse position:

{
  "lottie": [
    {
      "id": "eyes-follow",
      "container": "#eyes-lottie",
      "src": "/animations/character.json",
      "mouseTracking": {
        "enabled": true,
        "property": "rotation",
        "origin": { "x": 0.5, "y": 0.5 },
        "smoothing": 0.1
      }
    }
  ]
}

Mouse Tracking Configuration

interface LottieMouseTrackingConfig {
  enabled: boolean;              // Enable mouse tracking
  property?: 'rotation' | 'position'; // Property to animate
  origin?: { x: number; y: number };  // Origin point (0-1)
  smoothing?: number;            // Smoothing factor (0-1)
}

Rotation Tracking

Character/eyes follow mouse position by rotating:

{
  "mouseTracking": {
    "enabled": true,
    "property": "rotation",
    "origin": { "x": 0.5, "y": 0.5 },
    "smoothing": 0.15
  }
}

Position Tracking

Element moves toward mouse position:

{
  "mouseTracking": {
    "enabled": true,
    "property": "position",
    "smoothing": 0.05
  }
}

Common Patterns

Loading Animation

{
  "lottie": [
    {
      "id": "loader",
      "container": "#loader",
      "src": "/animations/loader.json",
      "renderer": "svg",
      "autoplay": true,
      "loop": true,
      "speed": 1.2
    }
  ]
}

Success/Error States

{
  "lottie": [
    {
      "id": "form-feedback",
      "container": "#feedback",
      "src": "/animations/feedback.json",
      "initial": "idle",
      "states": {
        "idle": { "segment": [0, 1], "loop": false },
        "loading": { "segment": [1, 60], "loop": true },
        "success": { "segment": [60, 120], "loop": false },
        "error": { "segment": [120, 180], "loop": false }
      },
      "transitions": [
        { "from": "idle", "to": "loading", "on": "submit" },
        { "from": "loading", "to": "success", "on": "success" },
        { "from": "loading", "to": "error", "on": "error" },
        { "from": "success", "to": "idle", "on": "reset" },
        { "from": "error", "to": "idle", "on": "reset" }
      ]
    }
  ]
}
{
  "lottie": [
    {
      "id": "menu-icon",
      "container": "#menu-icon",
      "src": "/animations/menu-icon.json",
      "renderer": "svg",
      "initial": "closed",
      "states": {
        "closed": { "segment": [0, 1] },
        "opening": { "segment": [1, 30] },
        "open": { "segment": [30, 31] },
        "closing": { "segment": [30, 60] }
      },
      "transitions": [
        { "from": "closed", "to": "opening", "on": "click" },
        { "from": "opening", "to": "open", "on": "complete" },
        { "from": "open", "to": "closing", "on": "click" },
        { "from": "closing", "to": "closed", "on": "complete" }
      ]
    }
  ]
}

Scroll Storytelling

{
  "lottie": [
    {
      "id": "story",
      "container": "#story-container",
      "src": "/animations/story.json",
      "scroll": {
        "trigger": ".story-section",
        "start": "top top",
        "end": "+=300%",
        "scrub": 0.5,
        "pin": true,
        "pinSpacing": true
      }
    }
  ]
}

Programmatic Control

After loading, control Lottie animations:

const result = await FasterMotion.load('/interactive.fmtion');

// Get Lottie controller
const lottie = result.fmtion?.lottie?.[0];

// Basic controls
lottie?.play();
lottie?.pause();
lottie?.stop();

// Frame control
lottie?.goToFrame(30);
lottie?.goToAndPlay(60);
lottie?.goToAndStop(90);

// State machine
lottie?.setState('hover');
lottie?.getState(); // Returns current state name

// Speed
lottie?.setSpeed(1.5);

// Direction
lottie?.setDirection(1);  // Forward
lottie?.setDirection(-1); // Reverse

Complete Example

{
  "meta": { "name": "Interactive Lottie Page" },
  "parameters": {
    "hero/scrollProgress": { "type": "float", "default": 0 }
  },
  "scrollBindings": [
    {
      "id": "hero-scroll",
      "parameter": "hero/scrollProgress",
      "trigger": ".hero",
      "start": "top top",
      "end": "bottom top"
    }
  ],
  "listeners": [],
  "dom": [],
  "canvas": [],
  "lottie": [
    {
      "id": "hero-mascot",
      "container": "#hero-mascot",
      "src": "/animations/mascot.json",
      "renderer": "svg",
      "scroll": {
        "trigger": ".hero",
        "start": "top top",
        "end": "bottom top",
        "scrub": true
      }
    },
    {
      "id": "cta-button",
      "container": "#cta-lottie",
      "src": "/animations/cta-button.json",
      "initial": "idle",
      "states": {
        "idle": { "segment": [0, 30], "loop": true },
        "hover": { "segment": [31, 60], "loop": false },
        "click": { "segment": [61, 90], "loop": false }
      },
      "transitions": [
        { "from": "idle", "to": "hover", "on": "mouseenter" },
        { "from": "hover", "to": "idle", "on": "mouseleave" },
        { "from": "hover", "to": "click", "on": "click" },
        { "from": "click", "to": "idle", "on": "complete" }
      ]
    },
    {
      "id": "character-eyes",
      "container": "#character",
      "src": "/animations/character.json",
      "autoplay": true,
      "loop": true,
      "mouseTracking": {
        "enabled": true,
        "property": "rotation",
        "origin": { "x": 0.5, "y": 0.3 },
        "smoothing": 0.1
      }
    }
  ]
}

See Also

On this page