or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

animation-cache.mdanimation-views.mdconfiguration.mdcontrols.mddotlottie.mddynamic-properties.mdindex.mdplayback-control.mdproviders.md
tile.json

playback-control.mddocs/

Playback Control

Comprehensive playback modes and control systems for fine-grained animation management including loop modes, playback states, and marker-based navigation.

Capabilities

LottiePlaybackMode

Main playback mode configuration system providing declarative control over animation playback behavior.

/**
 * Configuration for animation playback behavior
 * Supports both paused states and playing modes
 */
public enum LottiePlaybackMode {
    case paused(at: PausedState)
    case playing(_ mode: PlaybackMode)
}

/**
 * Specification for paused animation state
 */
public enum PausedState {
    /** Pause at current frame position */
    case currentFrame
    
    /** Pause at specific progress value */
    case progress(AnimationProgressTime)
    
    /** Pause at specific frame number */
    case frame(AnimationFrameTime)
    
    /** Pause at specific time in seconds */
    case time(TimeInterval)
    
    /** Pause at marker with optional position */
    case marker(String, position: MarkerPosition = .start)
}

/**
 * Marker position within marker duration
 */
public enum MarkerPosition {
    case start
    case end
}

/**
 * Specification for active playback behavior
 */
public enum PlaybackMode {
    /** Play between progress values with loop mode */
    case fromProgress(
        AnimationProgressTime,
        toProgress: AnimationProgressTime,
        loopMode: LottieLoopMode
    )
    
    /** Play between frame numbers with loop mode */
    case fromFrame(
        AnimationFrameTime,
        toFrame: AnimationFrameTime,
        loopMode: LottieLoopMode
    )
    
    /** Play between markers with options */
    case fromMarker(
        String,
        toMarker: String,
        playEndMarkerFrame: Bool = true,
        loopMode: LottieLoopMode
    )
    
    /** Play single marker with loop mode */
    case marker(String, loopMode: LottieLoopMode)
    
    /** Play sequence of markers */
    case markers([String])
}

Usage Examples:

import Lottie

class PlaybackController {
    let animationView = LottieAnimationView()
    
    func configurePlayback() {
        // Pause at specific states
        animationView.setPlaybackMode(.paused(at: .progress(0.5)))
        animationView.setPlaybackMode(.paused(at: .marker("checkpoint")))
        animationView.setPlaybackMode(.paused(at: .frame(30)))
        
        // Play with different modes
        animationView.setPlaybackMode(.playing(.fromProgress(0.2, toProgress: 0.8, loopMode: .loop)))
        animationView.setPlaybackMode(.playing(.marker("intro", loopMode: .playOnce)))
        animationView.setPlaybackMode(.playing(.fromMarker("start", toMarker: "end", loopMode: .autoReverse)))
        animationView.setPlaybackMode(.playing(.markers(["intro", "main", "outro"])))
    }
}

LottieLoopMode

Animation loop behavior configuration supporting various looping patterns and repetition counts.

/**
 * Animation loop behavior options
 */
public enum LottieLoopMode {
    /** Play animation once from beginning to end then stop */
    case playOnce
    
    /** Loop animation continuously from beginning to end */
    case loop
    
    /** Play forward to end, then backward to beginning, repeat */
    case autoReverse
    
    /** Loop specified number of times (fractional values supported) */
    case `repeat`(Float)
    
    /** Play forward/backward specified number of times */
    case repeatBackwards(Float)
}

Usage Examples:

import Lottie

class LoopingExamples {
    let animationView = LottieAnimationView()
    
    func demonstrateLoopModes() {
        // Basic loop modes
        animationView.loopMode = .playOnce
        animationView.loopMode = .loop
        animationView.loopMode = .autoReverse
        
        // Repeat specific number of times
        animationView.loopMode = .repeat(2.5) // Play 2.5 times
        animationView.loopMode = .repeatBackwards(3) // Forward/backward 3 times
        
        // Use with play methods
        animationView.play(
            fromProgress: 0,
            toProgress: 1,
            loopMode: .repeat(5)
        ) { finished in
            print("Repeated 5 times, finished: \(finished)")
        }
    }
}

LottieBackgroundBehavior

Behavior configuration for when the application moves to the background, providing different strategies for handling ongoing animations.

/**
 * Behavior when application moves to background
 */
public enum LottieBackgroundBehavior {
    /** Stop animation and reset to beginning */
    case stop
    
    /** Pause animation in current state */
    case pause
    
    /** Pause in background, restart when returning to foreground */
    case pauseAndRestore
    
    /** Stop animation and jump to end state */
    case forceFinish
    
    /** Continue playing animation in background */
    case continuePlaying
}

Usage Examples:

import Lottie

class BackgroundHandling {
    let animationView = LottieAnimationView()
    
    func configureBackgroundBehavior() {
        // For loading animations that should stop when backgrounded
        animationView.backgroundBehavior = .stop
        
        // For progress indicators that should pause and resume
        animationView.backgroundBehavior = .pauseAndRestore
        
        // For animations that must complete (e.g., form submission feedback)
        animationView.backgroundBehavior = .forceFinish
        
        // For ambient animations (use carefully for battery life)
        animationView.backgroundBehavior = .continuePlaying
    }
}

Animation Time Conversion

Helper methods for converting between different time representations in animations.

/**
 * Animation time conversion methods available on LottieAnimation
 */
extension LottieAnimation {
    
    /**
     * Get progress time for named marker
     * @param marker - Marker name to look up
     * @returns Progress time (0.0-1.0) for marker start, nil if not found
     */
    public func progressTime(forMarker marker: String) -> AnimationProgressTime?
    
    /**
     * Get frame time for named marker
     * @param marker - Marker name to look up
     * @returns Frame number for marker start, nil if not found
     */
    public func frameTime(forMarker marker: String) -> AnimationFrameTime?
    
    /**
     * Get duration frame time for named marker
     * @param marker - Marker name to look up
     * @returns Frame duration of marker, nil if not found
     */
    public func durationFrameTime(forMarker marker: String) -> AnimationFrameTime?
    
    /**
     * Convert frame number to progress value
     * @param frame - Frame number to convert
     * @param clamped - Whether to clamp result to 0.0-1.0 range
     * @returns Progress value (0.0-1.0)
     */
    public func progressTime(forFrame frame: AnimationFrameTime, clamped: Bool = true) -> AnimationProgressTime
    
    /**
     * Convert progress value to frame number
     * @param progress - Progress value (0.0-1.0) to convert
     * @returns Corresponding frame number
     */
    public func frameTime(forProgress progress: AnimationProgressTime) -> AnimationFrameTime
    
    /**
     * Convert frame number to time in seconds
     * @param frame - Frame number to convert
     * @returns Time in seconds
     */
    public func time(forFrame frame: AnimationFrameTime) -> TimeInterval
    
    /**
     * Convert time in seconds to frame number
     * @param time - Time in seconds to convert
     * @returns Corresponding frame number
     */
    public func frameTime(forTime time: TimeInterval) -> AnimationFrameTime
}

Usage Examples:

import Lottie

class TimeConversion {
    let animation = LottieAnimation.named("timeline")!
    
    func demonstrateConversions() {
        // Work with markers
        if let introProgress = animation.progressTime(forMarker: "intro") {
            print("Intro starts at progress: \(introProgress)")
        }
        
        if let outroFrame = animation.frameTime(forMarker: "outro") {
            print("Outro starts at frame: \(outroFrame)")
        }
        
        // Convert between time formats
        let midFrame = animation.frameTime(forProgress: 0.5)
        let midTime = animation.time(forFrame: midFrame)
        let backToProgress = animation.progressTime(forFrame: midFrame)
        
        print("Mid-point: progress=0.5, frame=\(midFrame), time=\(midTime)s")
        
        // Use conversions for precise playback
        let startFrame = animation.frameTime(forMarker: "highlight") ?? 0
        let endFrame = startFrame + 60 // Play for 60 frames
        let startProgress = animation.progressTime(forFrame: startFrame)
        let endProgress = animation.progressTime(forFrame: endFrame)
        
        // Play converted segment
        animationView.play(
            fromProgress: startProgress,
            toProgress: endProgress,
            loopMode: .playOnce
        )
    }
}

Playback State Monitoring

Properties and methods for monitoring current playback state and real-time animation values.

/**
 * Playback monitoring properties and methods
 */
extension LottieAnimationView {
    
    // MARK: - State Properties
    
    /** Whether animation is currently playing */
    public var isAnimationPlaying: Bool { get }
    
    /** Whether animation will play when added to window hierarchy */
    public var isAnimationQueued: Bool { get }
    
    /** Current progress from 0.0 to 1.0 */
    public var currentProgress: AnimationProgressTime { get set }
    
    /** Current time in seconds */
    public var currentTime: TimeInterval { get set }
    
    /** Current frame number */
    public var currentFrame: AnimationFrameTime { get set }
    
    /** Real-time frame while animation is playing (updates during playback) */
    public var realtimeAnimationFrame: AnimationFrameTime { get }
    
    /** Real-time progress while animation is playing (updates during playback) */
    public var realtimeAnimationProgress: AnimationProgressTime { get }
    
    /** Current playback mode configuration */
    public var currentPlaybackMode: LottiePlaybackMode? { get }
    
    /** Animation speed multiplier (1.0 = normal speed, 2.0 = double speed, etc.) */
    public var animationSpeed: CGFloat { get set }
    
    // MARK: - Control Methods
    
    /** Stop animation and reset to beginning */
    public func stop()
    
    /** Pause animation at current frame */
    public func pause()
    
    /**
     * Pause animation at specific state
     * @param pausedState - Where to pause the animation
     */
    public func pause(at pausedState: PausedState)
}

Usage Examples:

import Lottie

class PlaybackMonitoring {
    let animationView = LottieAnimationView()
    var displayLink: CADisplayLink?
    
    func startMonitoring() {
        displayLink = CADisplayLink(target: self, selector: #selector(updatePlaybackInfo))
        displayLink?.add(to: .main, forMode: .common)
    }
    
    @objc func updatePlaybackInfo() {
        guard animationView.isAnimationPlaying else { return }
        
        let currentFrame = animationView.realtimeAnimationFrame
        let currentProgress = animationView.realtimeAnimationProgress
        
        print("Playing: frame=\(currentFrame), progress=\(currentProgress)")
        
        // Update UI elements like progress bars, scrubbers, etc.
        updateProgressUI(progress: currentProgress)
    }
    
    func controlPlayback() {
        // Speed control
        animationView.animationSpeed = 2.0 // Double speed
        animationView.animationSpeed = 0.5 // Half speed
        
        // State control
        if animationView.isAnimationPlaying {
            animationView.pause()
        } else {
            animationView.play()
        }
        
        // Precise positioning
        animationView.pause(at: .progress(0.75))
        animationView.pause(at: .marker("checkpoint", position: .end))
    }
    
    func updateProgressUI(progress: AnimationProgressTime) {
        // Update progress indicator
    }
}

Advanced Playback Patterns

Complex playback scenarios combining multiple control mechanisms for sophisticated animation choreography.

/**
 * Advanced playback coordination methods
 */
extension LottieAnimationView {
    
    /**
     * Chain multiple playback sequences
     */
    func playSequence(
        segments: [(from: AnimationProgressTime, to: AnimationProgressTime, loopMode: LottieLoopMode)],
        completion: @escaping LottieCompletionBlock
    ) {
        guard !segments.isEmpty else {
            completion(true)
            return
        }
        
        var remainingSegments = segments
        let currentSegment = remainingSegments.removeFirst()
        
        play(
            fromProgress: currentSegment.from,
            toProgress: currentSegment.to,
            loopMode: currentSegment.loopMode
        ) { [weak self] finished in
            guard finished else {
                completion(false)
                return
            }
            
            self?.playSequence(segments: remainingSegments, completion: completion)
        }
    }
    
    /**
     * Coordinate animation with external timing
     */
    func synchronizeWithTimer(
        duration: TimeInterval,
        updateHandler: @escaping (AnimationProgressTime) -> Void,
        completion: @escaping LottieCompletionBlock
    ) {
        let startTime = CACurrentMediaTime()
        let timer = CADisplayLink(target: self, selector: #selector(timerUpdate))
        
        var timerCompletion: LottieCompletionBlock?
        timerCompletion = { finished in
            timer.invalidate()
            completion(finished)
        }
        
        // Store timer state (implementation would need proper storage)
        timer.add(to: .main, forMode: .common)
    }
}

Usage Examples:

import Lottie

class AdvancedPlaybackController {
    let animationView = LottieAnimationView()
    
    func demonstrateAdvancedPatterns() {
        // Sequential segment playback
        let segments = [
            (from: 0.0, to: 0.3, loopMode: LottieLoopMode.playOnce),
            (from: 0.3, to: 0.7, loopMode: LottieLoopMode.repeat(2)),
            (from: 0.7, to: 1.0, loopMode: LottieLoopMode.playOnce)
        ]
        
        animationView.playSequence(segments: segments) { finished in
            print("Complex sequence completed: \(finished)")
        }
        
        // Interactive scrubbing
        setupInteractiveScrubbing()
        
        // Synchronized multi-animation playback
        synchronizeAnimations()
    }
    
    func setupInteractiveScrubbing() {
        // Pause animation for manual control
        animationView.pause()
        
        // Add gesture recognizer for scrubbing
        let panGesture = UIPanGestureRecognizer(target: self, action: #selector(handleScrub(_:)))
        animationView.addGestureRecognizer(panGesture)
    }
    
    @objc func handleScrub(_ gesture: UIPanGestureRecognizer) {
        let translation = gesture.translation(in: animationView)
        let progress = max(0, min(1, animationView.currentProgress + translation.x / animationView.bounds.width))
        
        animationView.currentProgress = progress
        gesture.setTranslation(.zero, in: animationView)
    }
    
    func synchronizeAnimations() {
        let animation1 = LottieAnimationView(name: "sync1")
        let animation2 = LottieAnimationView(name: "sync2")
        
        // Start both animations simultaneously
        let group = DispatchGroup()
        
        group.enter()
        animation1.play { _ in group.leave() }
        
        group.enter()  
        animation2.play { _ in group.leave() }
        
        group.notify(queue: .main) {
            print("All synchronized animations completed")
        }
    }
}