lottie_pro 0.1.0 copy "lottie_pro: ^0.1.0" to clipboard
lottie_pro: ^0.1.0 copied to clipboard

Enhanced Lottie animations with custom controls and interactions. Supports all 6 platforms with WASM compatibility.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:lottie_pro/lottie_pro.dart';

void main() {
  runApp(const LottieProExampleApp());
}

class LottieProExampleApp extends StatelessWidget {
  const LottieProExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'LottiePro Example',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        useMaterial3: true,
      ),
      home: const LottieProExamplePage(),
    );
  }
}

class LottieProExamplePage extends StatefulWidget {
  const LottieProExamplePage({super.key});

  @override
  State<LottieProExamplePage> createState() => _LottieProExamplePageState();
}

class _LottieProExamplePageState extends State<LottieProExamplePage> {
  late LottieProController controller;
  late LottieProAnimation animation;
  double currentSpeed = 1.0;
  double currentFrame = 0.0;
  String interactionStatus = 'No interaction';
  int selectedSequenceIndex = 0;

  @override
  void initState() {
    super.initState();
    controller = LottieProController();
    animation = LottieProAnimation(controller: controller);

    // Create custom animation sequences
    _setupSequences();

    // Listen to frame changes and events
    controller.events.listen((event) {
      if (event == LottieProEvent.frameChanged) {
        setState(() {
          currentFrame = controller.currentFrame;
        });
      }
    });

    // Listen to sequence events
    animation.sequenceEvents.listen((event) {
      setState(() {
        interactionStatus = 'Sequence: ${event.sequence.name} - ${event.type.name}';
      });
    });
  }

  void _setupSequences() {
    // Create sequences list
    final sequences = <AnimationSequence>[
      // Sequence 1: Play and reverse
      AnimationSequence.playAndReverse(
        name: 'Bounce',
        speed: 1.5,
        waitTime: const Duration(milliseconds: 500),
      ),
      // Sequence 2: Fast play
      AnimationSequence.play(
        name: 'Fast Play',
        speed: 2.0,
        loop: false,
      ),
      // Sequence 3: Slow motion
      AnimationSequence.play(
        name: 'Slow Motion',
        speed: 0.5,
        loop: false,
      ),
    ];

    // Add sequences one by one
    for (final sequence in sequences) {
      animation.addSequence(sequence);
    }
  }

  List<LottieProInteraction> _buildInteractions() {
    return [
      // Touch interaction - tap to play
      TouchInteraction(
        interactionArea: const Rect.fromLTWH(0, 0, 300, 300),
        onTouch: (controller, position) {
          setState(() {
            interactionStatus = 'Tapped at: (${position.dx.toStringAsFixed(1)}, ${position.dy.toStringAsFixed(1)})';
          });
          controller.play();
        },
      ),
      // Hover interaction - speed up on hover
      HoverInteraction(
        interactionArea: const Rect.fromLTWH(0, 0, 300, 300),
        onHoverEnter: (controller, position) {
          setState(() {
            interactionStatus = 'Hovering - Speed increased!';
          });
          controller.setSpeed(2.0);
        },
        onHoverExit: (controller, position) {
          setState(() {
            interactionStatus = 'Hover ended - Normal speed';
          });
          controller.setSpeed(1.0);
        },
      ),
      // Drag interaction - control animation with drag
      DragInteraction(
        interactionArea: const Rect.fromLTWH(0, 0, 300, 300),
        onDragStart: (controller, position) {
          setState(() {
            interactionStatus = 'Drag started';
          });
        },
        onDragUpdate: (controller, position, delta) {
          // Map drag delta to frame changes
          final frameDelta = delta.dx * 0.1;
          final newFrame = (controller.currentFrame + frameDelta)
              .clamp(0.0, controller.totalFrames.toDouble());
          controller.goToFrame(newFrame.toInt());
          setState(() {
            interactionStatus = 'Dragging - Frame: ${newFrame.toStringAsFixed(1)}';
          });
        },
        onDragEnd: (controller, position, velocity) {
          setState(() {
            interactionStatus = 'Drag ended';
          });
        },
      ),
      // Scale interaction - pinch to zoom speed
      ScaleInteraction(
        interactionArea: const Rect.fromLTWH(0, 0, 300, 300),
        onScale: (controller, scale, focalPoint) {
          // Map scale to speed (1.0 to 3.0)
          final newSpeed = (scale * 1.5).clamp(0.5, 3.0);
          controller.setSpeed(newSpeed);
          setState(() {
            interactionStatus = 'Pinch scale: ${scale.toStringAsFixed(2)}x - Speed: ${newSpeed.toStringAsFixed(1)}x';
            currentSpeed = newSpeed;
          });
        },
      ),
    ];
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('LottiePro - All Features Demo'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            // Animation display area with interactions
            Container(
              width: 300,
              height: 300,
              decoration: BoxDecoration(
                border: Border.all(color: Colors.blue, width: 2),
                borderRadius: BorderRadius.circular(8),
              ),
              child: ClipRRect(
                borderRadius: BorderRadius.circular(8),
                child: LottiePro.asset(
                  'assets/animations/example.json',
                  controller: controller,
                  width: 300,
                  height: 300,
                  repeat: true,
                  interactions: _buildInteractions(),
                  allowCustomInteractions: true, // Set to false for interactive Lottie files
                  onLoaded: () {
                    debugPrint('Animation loaded successfully');
                    setState(() {
                      interactionStatus = 'Animation loaded - Try interactions!';
                    });
                  },
                  onComplete: () {
                    debugPrint('Animation completed');
                  },
                  onFrameChanged: (frame) {
                    setState(() {
                      currentFrame = frame;
                    });
                  },
                ),
              ),
            ),

            const SizedBox(height: 20),

            // Interaction status
            Card(
              color: Colors.blue.shade50,
              child: Padding(
                padding: const EdgeInsets.all(12.0),
                child: Row(
                  children: [
                    const Icon(Icons.touch_app, color: Colors.blue),
                    const SizedBox(width: 8),
                    Expanded(
                      child: Text(
                        interactionStatus,
                        style: Theme.of(context).textTheme.bodyMedium?.copyWith(
                              fontWeight: FontWeight.bold,
                            ),
                      ),
                    ),
                  ],
                ),
              ),
            ),

            const SizedBox(height: 20),

            // Animation info
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16.0),
                child: Column(
                  children: [
                    Text(
                      'Current Frame: ${currentFrame.toStringAsFixed(1)} / ${controller.totalFrames}',
                      style: Theme.of(context).textTheme.titleMedium,
                    ),
                    const SizedBox(height: 8),
                    Text(
                      'Speed: ${currentSpeed.toStringAsFixed(1)}x',
                      style: Theme.of(context).textTheme.titleMedium,
                    ),
                    const SizedBox(height: 8),
                    Text(
                      'State: ${controller.state.name}',
                      style: Theme.of(context).textTheme.titleMedium,
                    ),
                  ],
                ),
              ),
            ),

            const SizedBox(height: 20),

            // Control buttons
            Wrap(
              spacing: 8,
              runSpacing: 8,
              children: [
                ElevatedButton.icon(
                  onPressed: () => controller.play(),
                  icon: const Icon(Icons.play_arrow),
                  label: const Text('Play'),
                ),
                ElevatedButton.icon(
                  onPressed: () => controller.pause(),
                  icon: const Icon(Icons.pause),
                  label: const Text('Pause'),
                ),
                ElevatedButton.icon(
                  onPressed: () => controller.stop(),
                  icon: const Icon(Icons.stop),
                  label: const Text('Stop'),
                ),
                ElevatedButton.icon(
                  onPressed: () => controller.reverse(),
                  icon: const Icon(Icons.replay),
                  label: const Text('Reverse'),
                ),
              ],
            ),

            const SizedBox(height: 16),

            // Speed control
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16.0),
                child: Column(
                  children: [
                    const Text('Speed Control'),
                    const SizedBox(height: 8),
                    Row(
                      children: [
                        const Text('Speed: '),
                        Expanded(
                          child: Slider(
                            value: currentSpeed,
                            min: 0.1,
                            max: 3.0,
                            divisions: 29,
                            label: '${currentSpeed.toStringAsFixed(1)}x',
                            onChanged: (value) {
                              setState(() {
                                currentSpeed = value;
                              });
                              controller.setSpeed(value);
                            },
                          ),
                        ),
                      ],
                    ),
                  ],
                ),
              ),
            ),

            const SizedBox(height: 16),

            // Frame navigation
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16.0),
                child: Column(
                  children: [
                    const Text('Frame Navigation'),
                    const SizedBox(height: 8),
                    Wrap(
                      spacing: 8,
                      runSpacing: 8,
                      children: [
                        ElevatedButton(
                          onPressed: () => controller.previousFrame(),
                          child: const Text('⏮ Previous'),
                        ),
                        ElevatedButton(
                          onPressed: () => controller.goToStart(),
                          child: const Text('⏪ Start'),
                        ),
                        ElevatedButton(
                          onPressed: () => controller.goToEnd(),
                          child: const Text('⏩ End'),
                        ),
                        ElevatedButton(
                          onPressed: () => controller.nextFrame(),
                          child: const Text('Next ⏭'),
                        ),
                      ],
                    ),
                  ],
                ),
              ),
            ),

            const SizedBox(height: 16),

            // Custom Animation Sequences
            Card(
              child: Padding(
                padding: const EdgeInsets.all(16.0),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    const Text(
                      'Custom Animation Sequences',
                      style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
                    ),
                    const SizedBox(height: 8),
                    Wrap(
                      spacing: 8,
                      runSpacing: 8,
                      children: [
                        ElevatedButton(
                          onPressed: () {
                            selectedSequenceIndex = 0;
                            animation.playSequence(0);
                          },
                          style: ElevatedButton.styleFrom(
                            backgroundColor: selectedSequenceIndex == 0
                                ? Colors.blue
                                : null,
                          ),
                          child: const Text('Bounce'),
                        ),
                        ElevatedButton(
                          onPressed: () {
                            selectedSequenceIndex = 1;
                            animation.playSequence(1);
                          },
                          style: ElevatedButton.styleFrom(
                            backgroundColor: selectedSequenceIndex == 1
                                ? Colors.blue
                                : null,
                          ),
                          child: const Text('Fast Play'),
                        ),
                        ElevatedButton(
                          onPressed: () {
                            selectedSequenceIndex = 2;
                            animation.playSequence(2);
                          },
                          style: ElevatedButton.styleFrom(
                            backgroundColor: selectedSequenceIndex == 2
                                ? Colors.blue
                                : null,
                          ),
                          child: const Text('Slow Motion'),
                        ),
                      ],
                    ),
                    const SizedBox(height: 8),
                    ElevatedButton.icon(
                      onPressed: () => animation.playNextSequence(),
                      icon: const Icon(Icons.skip_next),
                      label: const Text('Next Sequence'),
                    ),
                  ],
                ),
              ),
            ),

            const SizedBox(height: 16),

            // Interaction Instructions
            Card(
              color: Colors.green.shade50,
              child: Padding(
                padding: const EdgeInsets.all(16.0),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Row(
                      children: [
                        const Icon(Icons.info, color: Colors.green),
                        const SizedBox(width: 8),
                        Text(
                          'Interactive Features',
                          style: Theme.of(context).textTheme.titleMedium?.copyWith(
                                fontWeight: FontWeight.bold,
                              ),
                        ),
                      ],
                    ),
                    const SizedBox(height: 12),
                    _buildInstruction('👆 Tap', 'Play animation'),
                    _buildInstruction('🖱️ Hover', 'Speed up (desktop/web)'),
                    _buildInstruction('👈👉 Drag', 'Scrub through frames'),
                    _buildInstruction('🤏 Pinch', 'Control speed (mobile)'),
                  ],
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildInstruction(String icon, String text) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 4.0),
      child: Row(
        children: [
          Text(icon, style: const TextStyle(fontSize: 20)),
          const SizedBox(width: 8),
          Text(text),
        ],
      ),
    );
  }

  @override
  void dispose() {
    controller.dispose();
    animation.dispose();
    super.dispose();
  }
}
2
likes
160
points
21
downloads

Publisher

verified publisherbechattaoui.dev

Weekly Downloads

Enhanced Lottie animations with custom controls and interactions. Supports all 6 platforms with WASM compatibility.

Repository (GitHub)
View/report issues

Topics

#flutter #lottie #animation #interactive #ui

Documentation

Documentation
API reference

Funding

Consider supporting this project:

github.com

License

MIT (license)

Dependencies

flutter, lottie

More

Packages that depend on lottie_pro