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

providers.mddocs/

Providers

Extensible provider system for supplying external assets like images, fonts, and text to Lottie animations, enabling dynamic content replacement and customization.

Capabilities

AnimationImageProvider

Protocol-based system for providing external images referenced in Lottie animations, supporting dynamic image replacement and custom image sources.

/**
 * Protocol for providing images to animations
 * Enables dynamic image replacement and custom image sources
 */
public protocol AnimationImageProvider {
    
    /**
     * Provide image for animation asset
     * @param asset - Image asset information from animation
     * @returns CGImage for the asset, nil if not available
     */
    func imageForAsset(asset: ImageAsset) -> CGImage?
    
    /**
     * Provide content gravity for image asset (optional)
     * @param asset - Image asset to get gravity for
     * @returns Content gravity mode for layer display
     */
    func contentsGravity(for asset: ImageAsset) -> CALayerContentsGravity
    
    /**
     * Whether provider results can be cached (optional)
     * @returns true if results are stable and can be cached
     */
    var cacheEligible: Bool { get }
}

/**
 * Image asset information from animation
 * Contains metadata about referenced external images
 */
public struct ImageAsset {
    
    /** Unique identifier for the image asset */
    public let id: String
    
    /** Name of the image file */
    public let name: String
    
    /** Directory path for the image */
    public let directory: String
    
    /** Original width of the image */
    public let width: Double
    
    /** Original height of the image */
    public let height: Double
}

Default Implementation:

/**
 * Default implementation providing optional methods
 */
extension AnimationImageProvider {
    
    public func contentsGravity(for asset: ImageAsset) -> CALayerContentsGravity {
        return .resizeAspectFill
    }
    
    public var cacheEligible: Bool {
        return true
    }
}

BundleImageProvider

Built-in image provider that loads images from application bundles, supporting different bundle sources and subdirectories.

/**
 * Image provider that loads images from application bundles
 * Supports main bundle, custom bundles, and subdirectories
 */
public class BundleImageProvider: AnimationImageProvider {
    
    /** Bundle to search for images */
    public let bundle: Bundle
    
    /** Optional subdirectory within bundle */
    public let searchPath: String?
    
    /**
     * Initialize with bundle and optional subdirectory
     * @param bundle - Bundle to search for images (defaults to main bundle)
     * @param searchPath - Optional subdirectory path within bundle
     */
    public init(bundle: Bundle = Bundle.main, searchPath: String? = nil)
    
    /**
     * Load image from bundle for asset
     * @param asset - Asset information from animation
     * @returns CGImage loaded from bundle, nil if not found
     */
    public func imageForAsset(asset: ImageAsset) -> CGImage?
    
    public func contentsGravity(for asset: ImageAsset) -> CALayerContentsGravity
    public var cacheEligible: Bool { true }
}

Usage Examples:

import Lottie
import UIKit

class BundleImageProviderExamples {
    
    func setupBundleProviders() {
        // Default main bundle provider
        let mainBundleProvider = BundleImageProvider()
        
        // Custom bundle provider
        guard let customBundle = Bundle(identifier: "com.example.assets") else { return }
        let customBundleProvider = BundleImageProvider(bundle: customBundle)
        
        // Subdirectory provider
        let subdirectoryProvider = BundleImageProvider(
            bundle: Bundle.main,
            searchPath: "animations/images"
        )
        
        // Use with animation view
        let animationView = LottieAnimationView(
            animation: LottieAnimation.named("character"),
            imageProvider: subdirectoryProvider
        )
    }
    
    func createAnimationWithBundleImages() {
        // Load animation that references external images
        let animation = LottieAnimation.named("avatar_animation")
        
        // Set up provider for animation images stored in bundle
        let imageProvider = BundleImageProvider(
            bundle: Bundle.main,
            searchPath: "avatar_assets"
        )
        
        let animationView = LottieAnimationView(
            animation: animation,
            imageProvider: imageProvider
        )
        
        // Images will be loaded from main bundle's "avatar_assets" folder
        animationView.play()
    }
}

FilepathImageProvider

Image provider that loads images from file system paths, supporting absolute paths, URL-based paths, and data URLs.

/**
 * Image provider that loads images from file system paths
 * Supports absolute paths, URLs, and data URL schemes
 */
public class FilepathImageProvider: AnimationImageProvider {
    
    /** Base directory URL for relative image paths */
    public let filepath: URL
    
    /** Content gravity for rendered images */
    public let contentsGravity: CALayerContentsGravity
    
    /**
     * Initialize with file path string
     * @param filepath - Absolute file path to directory containing images
     * @param contentsGravity - Content gravity for image rendering
     */
    public init(filepath: String, contentsGravity: CALayerContentsGravity = .resize)
    
    /**
     * Initialize with file URL
     * @param filepath - URL to directory containing images  
     * @param contentsGravity - Content gravity for image rendering
     */
    public init(filepath: URL, contentsGravity: CALayerContentsGravity = .resize)
    
    /**
     * Load image from file system for asset
     * Supports data URLs and standard file paths
     * @param asset - Asset information from animation
     * @returns CGImage loaded from file, nil if not found
     */
    public func imageForAsset(asset: ImageAsset) -> CGImage?
    
    public func contentsGravity(for asset: ImageAsset) -> CALayerContentsGravity
    public var cacheEligible: Bool { true }
}

Usage Examples:

import Lottie

class FilepathImageProviderExamples {
    
    func setupFilepathProvider() {
        // Provider for images in documents directory
        let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
        let documentsProvider = FilepathImageProvider(searchPath: documentsPath)
        
        // Provider for images in specific directory
        let customPath = "/Users/developer/project/assets/images"
        let customProvider = FilepathImageProvider(searchPath: customPath)
        
        // Use with animation
        let animationView = LottieAnimationView(
            animation: LottieAnimation.named("user_content"),
            imageProvider: documentsProvider
        )
    }
    
    func loadDynamicImages() {
        // Load images from user-generated content directory
        let userContentPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
            .appendingPathComponent("user_images").path
        
        let dynamicProvider = FilepathImageProvider(searchPath: userContentPath)
        
        let animationView = LottieAnimationView(
            animation: LottieAnimation.named("dynamic_content"),
            imageProvider: dynamicProvider
        )
        
        // Animation will load images from user content directory
        animationView.play()
    }
}

Custom Image Providers

Creating custom image providers for specialized use cases like network images, generated content, or cached resources.

/**
 * Example custom image provider for network images
 */
class NetworkImageProvider: AnimationImageProvider {
    
    private var imageCache: [String: CGImage] = [:]
    private let baseURL: URL
    
    init(baseURL: URL) {
        self.baseURL = baseURL
    }
    
    func imageForAsset(asset: ImageAsset) -> CGImage? {
        // Check cache first
        if let cachedImage = imageCache[asset.name] {
            return cachedImage
        }
        
        // Load from network (simplified example)
        let imageURL = baseURL.appendingPathComponent(asset.name)
        
        // In real implementation, this would be asynchronous
        if let data = try? Data(contentsOf: imageURL),
           let image = CGImage.create(from: data) {
            imageCache[asset.name] = image
            return image
        }
        
        return nil
    }
    
    var cacheEligible: Bool { false } // Network images shouldn't be cached by Lottie
}

/**
 * Example custom image provider for generated content
 */
class GeneratedImageProvider: AnimationImageProvider {
    
    func imageForAsset(asset: ImageAsset) -> CGImage? {
        // Generate image based on asset properties
        return generateImage(
            name: asset.name,
            size: CGSize(width: asset.width, height: asset.height)
        )
    }
    
    private func generateImage(name: String, size: CGSize) -> CGImage? {
        // Create context
        guard let context = CGContext(
            data: nil,
            width: Int(size.width),
            height: Int(size.height),
            bitsPerComponent: 8,
            bytesPerRow: 0,
            space: CGColorSpaceCreateDeviceRGB(),
            bitmapInfo: CGImageAlphaInfo.premultipliedLast.rawValue
        ) else { return nil }
        
        // Generate content based on name
        if name.contains("gradient") {
            drawGradient(in: context, size: size)
        } else if name.contains("pattern") {
            drawPattern(in: context, size: size)
        } else {
            drawDefault(in: context, size: size)
        }
        
        return context.makeImage()
    }
    
    private func drawGradient(in context: CGContext, size: CGSize) {
        // Implementation for gradient generation
    }
    
    private func drawPattern(in context: CGContext, size: CGSize) {
        // Implementation for pattern generation
    }
    
    private func drawDefault(in context: CGContext, size: CGSize) {
        // Implementation for default image generation
    }
    
    var cacheEligible: Bool { true } // Generated images can be cached
}

AnimationFontProvider

Protocol-based system for providing custom fonts to text layers in animations, enabling dynamic font replacement and custom typography.

/**
 * Protocol for providing fonts to animations
 * Enables custom font replacement and dynamic typography
 */
public protocol AnimationFontProvider {
    
    /**
     * Provide font for family and size
     * @param family - Font family name from animation
     * @param size - Font size in points
     * @returns CTFont for the specified family and size, nil to use default
     */
    func fontFor(family: String, size: CGFloat) -> CTFont?
}

/**
 * Default font provider implementation
 * Uses system fonts as fallback for missing custom fonts
 */
public final class DefaultFontProvider: AnimationFontProvider {
    
    /**
     * Initialize default font provider
     */
    public init()
    
    /**
     * Provide system font for family and size
     * @param family - Font family name (ignored, uses system font)
     * @param size - Font size in points
     * @returns System font at specified size
     */
    public func fontFor(family: String, size: CGFloat) -> CTFont? {
        return CTFontCreateWithName("HelveticaNeue" as CFString, size, nil)
    }
}

Usage Examples:

import Lottie
import CoreText

class CustomFontProvider: AnimationFontProvider {
    
    private let fontMapping: [String: String] = [
        "BrandFont-Regular": "MyCustomFont-Regular",
        "BrandFont-Bold": "MyCustomFont-Bold",
        "BrandFont-Light": "MyCustomFont-Light"
    ]
    
    func fontFor(family: String, size: CGFloat) -> CTFont? {
        // Map animation font names to actual font names
        let actualFontName = fontMapping[family] ?? family
        
        // Try to create the requested font
        if let font = CTFontCreateWithName(actualFontName as CFString, size, nil) {
            return font
        }
        
        // Fallback to system font
        return CTFontCreateWithName("HelveticaNeue" as CFString, size, nil)
    }
}

class FontProviderExamples {
    
    func setupCustomFonts() {
        let customFontProvider = CustomFontProvider()
        
        let animationView = LottieAnimationView(
            animation: LottieAnimation.named("text_animation"),
            fontProvider: customFontProvider
        )
        
        // Text in animation will use custom fonts
        animationView.play()
    }
    
    func setupDynamicFonts() {
        let dynamicFontProvider = DynamicFontProvider()
        
        let animationView = LottieAnimationView(
            animation: LottieAnimation.named("responsive_text"),
            fontProvider: dynamicFontProvider
        )
        
        // Fonts will adapt to accessibility settings
        animationView.play()
    }
}

class DynamicFontProvider: AnimationFontProvider {
    
    func fontFor(family: String, size: CGFloat) -> CTFont? {
        // Adapt font size based on accessibility settings
        let preferredSize = UIFontMetrics.default.scaledValue(for: size)
        
        // Use preferred content size category
        let fontDescriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: .body)
        let font = CTFontCreateWithFontDescriptor(fontDescriptor, preferredSize, nil)
        
        return font
    }
}

AnimationKeypathTextProvider

Protocol-based system for providing dynamic text replacement in animations, enabling localization and runtime text modification.

/**
 * Protocol for providing dynamic text to animations
 * Enables text replacement, localization, and dynamic content
 */
public protocol AnimationKeypathTextProvider {
    
    /**
     * Provide text for keypath and source text
     * @param keypath - Animation keypath for text element
     * @param sourceText - Original text from animation (may be nil)
     * @returns Replacement text, nil to use original text
     */
    func text(for keypath: AnimationKeypath, sourceText: String?) -> String?
}

/**
 * Default text provider that uses original animation text
 */
public final class DefaultTextProvider: AnimationKeypathTextProvider {
    
    public init()
    
    /**
     * Return original text without modification
     * @param keypath - Animation keypath (ignored)
     * @param sourceText - Original text from animation
     * @returns Original text unchanged
     */
    public func text(for keypath: AnimationKeypath, sourceText: String?) -> String? {
        return sourceText
    }
}

/**
 * Dictionary-based text provider for simple text replacement
 */
public final class DictionaryTextProvider: AnimationKeypathTextProvider {
    
    private let textMap: [String: String]
    
    /**
     * Initialize with text mapping dictionary
     * @param textMap - Dictionary mapping keypaths to replacement text
     */
    public init(_ textMap: [String: String])
    
    /**
     * Provide text based on keypath lookup
     * @param keypath - Animation keypath to look up
     * @param sourceText - Original text (used as fallback)
     * @returns Mapped text or original text if no mapping found
     */
    public func text(for keypath: AnimationKeypath, sourceText: String?) -> String? {
        return textMap[keypath.string] ?? sourceText
    }
}

Usage Examples:

import Lottie

class TextProviderExamples {
    
    func setupDictionaryTextProvider() {
        let textMapping = [
            "welcome.title": "Welcome!",
            "welcome.subtitle": "Get started with our app",
            "button.text": "Continue",
            "footer.copyright": "© 2024 My Company"
        ]
        
        let textProvider = DictionaryTextProvider(textMapping)
        
        let animationView = LottieAnimationView(
            animation: LottieAnimation.named("welcome_screen"),
            textProvider: textProvider
        )
        
        // Text elements will be replaced with mapped values
        animationView.play()
    }
    
    func setupLocalizationProvider() {
        let localizationProvider = LocalizationTextProvider()
        
        let animationView = LottieAnimationView(
            animation: LottieAnimation.named("localized_content"),
            textProvider: localizationProvider
        )
        
        // Text will be localized based on current locale
        animationView.play()
    }
}

/**
 * Custom text provider for localization
 */
class LocalizationTextProvider: AnimationKeypathTextProvider {
    
    func text(for keypath: AnimationKeypath, sourceText: String?) -> String? {
        // Use keypath as localization key
        let localizedText = NSLocalizedString(keypath.string, comment: "Animation text")
        
        // Return localized text if different from key, otherwise use source
        return localizedText != keypath.string ? localizedText : sourceText
    }
}

/**
 * Dynamic text provider with real-time data
 */
class DynamicTextProvider: AnimationKeypathTextProvider {
    
    private let dataSource: DataSource
    
    init(dataSource: DataSource) {
        self.dataSource = dataSource
    }
    
    func text(for keypath: AnimationKeypath, sourceText: String?) -> String? {
        // Provide dynamic text based on keypath and current data
        switch keypath.string {
        case "user.name":
            return dataSource.currentUser?.name ?? sourceText
        case "stats.count":
            return "\(dataSource.currentCount)"
        case "time.display":
            return DateFormatter.shortTime.string(from: Date())
        default:
            return sourceText
        }
    }
}

protocol DataSource {
    var currentUser: User? { get }
    var currentCount: Int { get }
}

struct User {
    let name: String
}

extension DateFormatter {
    static let shortTime: DateFormatter = {
        let formatter = DateFormatter()
        formatter.timeStyle = .short
        return formatter
    }()
}

Provider Coordination

Advanced patterns for coordinating multiple providers and handling provider updates during animation playback.

/**
 * Coordinated provider system for complex animations
 */
class CoordinatedProviderSystem {
    
    let imageProvider: AnimationImageProvider
    let fontProvider: AnimationFontProvider
    let textProvider: AnimationKeypathTextProvider
    
    init(
        imageProvider: AnimationImageProvider,
        fontProvider: AnimationFontProvider,
        textProvider: AnimationKeypathTextProvider
    ) {
        self.imageProvider = imageProvider
        self.fontProvider = fontProvider
        self.textProvider = textProvider
    }
    
    func setupAnimationView() -> LottieAnimationView {
        return LottieAnimationView(
            animation: LottieAnimation.named("complex_animation"),
            imageProvider: imageProvider,
            textProvider: textProvider,
            fontProvider: fontProvider
        )
    }
}

/**
 * Provider that adapts to user preferences and system settings
 */
class AdaptiveProviderSystem {
    
    func createAdaptiveProviders() -> (AnimationImageProvider, AnimationFontProvider, AnimationKeypathTextProvider) {
        // Adapt to user preferences
        let userPreferences = UserDefaults.standard
        
        // Image provider based on quality preference
        let imageProvider: AnimationImageProvider
        if userPreferences.bool(forKey: "highQualityImages") {
            imageProvider = BundleImageProvider(bundle: Bundle.main, searchPath: "hd_images")
        } else {
            imageProvider = BundleImageProvider(bundle: Bundle.main, searchPath: "sd_images")
        }
        
        // Font provider based on accessibility
        let fontProvider = AccessibilityFontProvider()
        
        // Text provider based on locale
        let textProvider = LocaleAwareTextProvider()
        
        return (imageProvider, fontProvider, textProvider)
    }
}

class AccessibilityFontProvider: AnimationFontProvider {
    
    func fontFor(family: String, size: CGFloat) -> CTFont? {
        // Respect Dynamic Type and accessibility settings
        let metrics = UIFontMetrics.default
        let adjustedSize = metrics.scaledValue(for: size)
        
        // Use accessibility-friendly fonts when bold text is enabled
        if UIAccessibility.isBoldTextEnabled {
            let boldFontName = family + "-Bold"
            return CTFontCreateWithName(boldFontName as CFString, adjustedSize, nil)
        }
        
        return CTFontCreateWithName(family as CFString, adjustedSize, nil)
    }
}

class LocaleAwareTextProvider: AnimationKeypathTextProvider {
    
    func text(for keypath: AnimationKeypath, sourceText: String?) -> String? {
        // Get localized text for current locale
        let bundle = Bundle.main
        let localizedText = bundle.localizedString(forKey: keypath.string, value: sourceText, table: "Animations")
        
        // Apply locale-specific formatting if needed
        return formatForLocale(localizedText)
    }
    
    private func formatForLocale(_ text: String?) -> String? {
        guard let text = text else { return nil }
        
        // Apply RTL adjustments, number formatting, etc.
        let locale = Locale.current
        if locale.characterDirection == .rightToLeft {
            // Apply RTL-specific adjustments
        }
        
        return text
    }
}

Usage Examples:

import Lottie

class AdvancedProviderExamples {
    
    func setupAdaptiveAnimation() {
        let adaptiveSystem = AdaptiveProviderSystem()
        let (imageProvider, fontProvider, textProvider) = adaptiveSystem.createAdaptiveProviders()
        
        let animationView = LottieAnimationView(
            animation: LottieAnimation.named("adaptive_content"),
            imageProvider: imageProvider,
            textProvider: textProvider,
            fontProvider: fontProvider
        )
        
        // Animation will adapt to user preferences and system settings
        animationView.play()
    }
    
    func updateProvidersAtRuntime() {
        let animationView = LottieAnimationView()
        
        // Update providers based on runtime conditions
        if shouldUseHighQualityAssets() {
            animationView.imageProvider = BundleImageProvider(searchPath: "hd_assets")
        } else {
            animationView.imageProvider = BundleImageProvider(searchPath: "sd_assets")
        }
        
        // Update text for different user states
        if isUserLoggedIn() {
            let userTextProvider = DictionaryTextProvider([
                "greeting": "Welcome back, \(getCurrentUserName())!",
                "action": "Continue"
            ])
            animationView.textProvider = userTextProvider
        } else {
            let guestTextProvider = DictionaryTextProvider([
                "greeting": "Welcome!",
                "action": "Sign In"
            ])
            animationView.textProvider = guestTextProvider
        }
    }
    
    func shouldUseHighQualityAssets() -> Bool {
        // Check network conditions, battery level, device capabilities
        return true
    }
    
    func isUserLoggedIn() -> Bool {
        return false
    }
    
    func getCurrentUserName() -> String {
        return "User"
    }
}