Back to Slint

Animation System Internals

docs/development/animation-internals.md

1.16.14.0 KB
Original Source

Animation System Internals

Note for AI coding assistants (agents): When to load this document: Working on internal/core/animations.rs, debugging animation timing issues, or optimizing animation performance. For general build commands and project structure, see /AGENTS.md.

Animation Timing System

Slint animations use a mocked time system rather than real-time clocks. This provides:

  • Deterministic animation behavior for testing
  • Frame-rate independence
  • Consistent behavior across platforms

The animation driver (internal/core/animations.rs) manages a global instant that advances each frame:

AnimationDriver
├── global_instant: Property<Instant>  // Current animation time
├── active_animations: bool            // Whether animations are running
└── update_animations(new_tick)        // Called per frame by the backend

Key components:

Function/TypeLocationPurpose
Instantinternal/core/animations.rsMilliseconds since animation driver started
current_tick()internal/core/animations.rsGet current animation time (registers dependency)
animation_tick()internal/core/animations.rsSame, but signals a frame is needed
update_timers_and_animations()internal/core/platform.rsCalled by platform each frame
EasingCurveinternal/core/items.rsEnum of easing curve types

Easing Curve Implementation

Easing curves are defined in the EasingCurve enum in internal/core/items.rs. The interpolation logic is in internal/core/animations.rs.

For cubic-bezier(a, b, c, d), Slint uses a binary search algorithm to find the t parameter for a given x value, then evaluates the y component of the bezier curve.

Standard easings (ease-in, ease-out, ease-in-out, etc.) are pre-defined cubic bezier curves.

Animation Performance

Each animated property:

  1. Re-evaluates its binding every frame
  2. Marks dependents dirty
  3. Triggers re-rendering of affected items

Efficient to animate (no layout recalculation):

  • x, y - Position
  • opacity - Transparency
  • rotation-angle - Rotation
  • background - Colors/gradients

Expensive to animate (triggers layout):

  • width, height
  • preferred-width, preferred-height
  • Any property that affects sibling positioning

Debugging Animations

Slow Motion

sh
# Slow animations by factor of 4
SLINT_SLOW_ANIMATIONS=4 cargo run

# Slow by factor of 10 for detailed inspection
SLINT_SLOW_ANIMATIONS=10 cargo run

Useful for:

  • Verifying easing curves
  • Checking animation start/end states
  • Debugging timing between multiple animations

Checking Active Animations

rust
// In application code
if window.has_active_animations() {
    // Animations are in progress
}

Mock Time in Tests

For deterministic testing without real-time waits:

rust
use slint_testing::mock_elapsed_time;

// Advance animation time by 100ms
mock_elapsed_time(100);

// Complete a 300ms animation
mock_elapsed_time(300);

This is implemented in internal/core/tests/ and used throughout the test suite.

Key Files

FilePurpose
internal/core/animations.rsAnimation driver, timing, interpolation
internal/core/items.rsEasingCurve enum definition
internal/core/timers.rsTimer integration with animation system
internal/core/platform.rsupdate_timers_and_animations() entry point

Common Modification Patterns

Adding a New Easing Curve

  1. Add variant to EasingCurve enum in internal/core/items.rs
  2. Handle interpolation in internal/core/animations.rs
  3. Add parsing support in internal/compiler/ if new syntax needed
  4. Add tests in tests/cases/

Debugging Animation Glitches

  1. Use SLINT_SLOW_ANIMATIONS=10 to slow down
  2. Check if issue is in timing (animations.rs) or rendering (renderers/)
  3. Add eprintln! in update_animations() to trace tick values
  4. Use screenshot tests to capture specific animation frames