flutter_animated_circle 0.1.1

SDKflutter
Platformandroidioswindowslinuxmacosweb

Beautiful animated circles and pie charts for Flutter. Smooth animations, multi-segment support, scroll triggers, and extensive customization.

Flutter Animated Circle

Pub Package Pub Points Platform Support License: MIT

A production-ready Flutter package that provides beautiful, customizable animated circular widgets with smooth animations and extensive configuration options. Perfect for creating progress indicators, pie charts, data visualizations, and engaging UI elements.

Flutter Animated Circle Showcase

🎯 Key Features

  • 🎨 Full Circle Animation: Smooth, customizable circular progress indicators with configurable timing
  • 📊 Segmented Circles: Multi-colored segments ideal for pie charts, data visualization, and progress tracking
  • 🥧 Animated Pie Charts: Filled pie chart slices with sequential animation and customizable styling
  • 🔄 Scroll-Triggered Animation: Intelligent viewport detection with automatic animation triggering
  • ⚙️ Extensive Customization: Granular control over colors, stroke widths, borders, spacing, and timing
  • 🚀 Performance Optimized: Efficient rendering with RepaintBoundary and optimized painters
  • 📱 Cross-Platform: Full support for Android, iOS, Web, Windows, macOS, and Linux
  • 🎭 Animation Curves: Support for all Flutter animation curves and custom easing functions

🚀 Getting Started

Installation

Add flutter_animated_circle to your pubspec.yaml:

dependencies:
  flutter_animated_circle: ^0.1.0

Then run:

flutter pub get

Import

import 'package:flutter_animated_circle/flutter_animated_circle.dart';

📖 Usage Examples

Basic Usage

Simple Progress Circle

AnimatedCircleView(
  circlePainterConfig: CirclePainterConfig.full(
    fillColor: Colors.blue,
    borderColor: Colors.blue.shade800,
    strokeWidth: 16.0,
    borderWidth: 20.0,
  ),
  duration: const Duration(milliseconds: 800),
)

Multi-Segment Data Visualization

AnimatedCircleView(
  circlePainterConfig: CirclePainterConfig.segmented(
    segments: [
      CircleSegment(
        fillColor: Colors.blue, 
        borderColor: Colors.blue.shade800,
        ratio: 0.6, // 60% of the circle
      ),
      CircleSegment(
        fillColor: Colors.green, 
        borderColor: Colors.green.shade800,
        ratio: 0.4, // 40% of the circle
      ),
    ],
    strokeWidth: 16.0,
    borderWidth: 20.0,
  ),
  duration: const Duration(milliseconds: 800),
)

Filled Pie Chart

AnimatedPieChartView(
  pieChartPainterConfig: PieChartPainterConfig(
    data: [
      PieData(value: 35, color: Colors.blue, label: 'Technology'),
      PieData(value: 25, color: Colors.green, label: 'Finance'),
      PieData(value: 20, color: Colors.orange, label: 'Healthcare'),
      PieData(value: 12, color: Colors.purple, label: 'Education'),
      PieData(value: 8, color: Colors.red, label: 'Other'),
    ],
    strokeWidth: 2.0,
    separatorAngle: 0.02,
  ),
  duration: const Duration(milliseconds: 1500),
)

Advanced Features

Scroll-Triggered Animation

Automatically animate circles when they become visible during scrolling:

class ScrollableCircles extends StatefulWidget {
  @override
  State<ScrollableCircles> createState() => _ScrollableCirclesState();
}

class _ScrollableCirclesState extends State<ScrollableCircles> {
  final ScrollController _scrollController = ScrollController();

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      controller: _scrollController,
      itemCount: 10,
      itemBuilder: (context, index) {
        return Container(
          height: 400,
          padding: const EdgeInsets.all(20),
          child: AnimatedCircleView(
            circlePainterConfig: CirclePainterConfig.full(
              fillColor: Colors.amber,
              borderColor: Colors.amber.shade800,
            ),
            scrollController: _scrollController,
            duration: const Duration(milliseconds: 600),
            onAnimationCompleted: () {
              print('Circle $index animation completed!');
            },
          ),
        );
      },
    );
  }

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }
}

Scroll-Triggered Pie Charts

class ScrollablePieCharts extends StatefulWidget {
  @override
  State<ScrollablePieCharts> createState() => _ScrollablePieChartsState();
}

class _ScrollablePieChartsState extends State<ScrollablePieCharts> {
  final ScrollController _scrollController = ScrollController();

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      controller: _scrollController,
      itemCount: 5,
      itemBuilder: (context, index) {
        return Container(
          height: 400,
          padding: const EdgeInsets.all(20),
          child: AnimatedPieChartView(
            pieChartPainterConfig: PieChartPainterConfig(
              data: [
                PieData(value: 40, color: Colors.blue.shade400),
                PieData(value: 30, color: Colors.green.shade400),
                PieData(value: 20, color: Colors.orange.shade400),
                PieData(value: 10, color: Colors.purple.shade400),
              ],
            ),
            scrollController: _scrollController,
            duration: const Duration(milliseconds: 1200),
            onAnimationCompleted: () {
              print('Pie chart $index animation completed!');
            },
          ),
        );
      },
    );
  }

  @override
  void dispose() {
    _scrollController.dispose();
    super.dispose();
  }
}

Complex Multi-Segment Circle with Custom Styling

AnimatedCircleView(
  circlePainterConfig: CirclePainterConfig.segmented(
    segments: [
      CircleSegment(
        fillColor: Colors.red.shade400, 
        borderColor: Colors.red.shade700, 
        ratio: 0.25
      ),
      CircleSegment(
        fillColor: Colors.blue.shade400, 
        borderColor: Colors.blue.shade700, 
        ratio: 0.25
      ),
      CircleSegment(
        fillColor: Colors.green.shade400, 
        borderColor: Colors.green.shade700, 
        ratio: 0.25
      ),
      CircleSegment(
        fillColor: Colors.purple.shade400, 
        borderColor: Colors.purple.shade700, 
        ratio: 0.25
      ),
    ],
    separatorAngle: 0.05, // 5-degree gaps between segments
    baseColor: Colors.grey.shade200, // Background color
    strokeWidth: 18.0,
    borderWidth: 22.0,
  ),
  duration: const Duration(milliseconds: 1200),
  fadeInDuration: const Duration(milliseconds: 300),
  curve: Curves.easeInOutCubic,
  onAnimationCompleted: () {
    print("Multi-segment animation completed!");
  },
)

📋 API Reference

AnimatedCircleView

The main widget for displaying animated circles.

PropertyTypeDefaultDescription
circlePainterConfigCirclePainterConfigrequiredConfiguration for circle appearance and segments
scrollControllerScrollController?nullEnables scroll-triggered animation when provided
onAnimationCompletedVoidCallback?nullCallback fired when animation completes
durationDuration600msDuration of the circle drawing animation
fadeInDurationDuration200msDuration of fade-in effect
curveCurveCurves.easeInAnimation curve for drawing animation
strokeWidthdouble16.0Width of circle's inner stroke
borderWidthdouble20.0Width of circle's outer border

AnimatedPieChartView

The main widget for displaying animated filled pie charts.

PropertyTypeDefaultDescription
pieChartPainterConfigPieChartPainterConfigrequiredConfiguration for pie chart data and appearance
scrollControllerScrollController?nullEnables scroll-triggered animation when provided
onAnimationCompletedVoidCallback?nullCallback fired when animation completes
durationDuration1200msDuration of the pie chart drawing animation
fadeInDurationDuration300msDuration of fade-in effect
curveCurveCurves.easeInOutAnimation curve for drawing animation

CirclePainterConfig

Configuration class that defines the visual appearance of circles.

CirclePainterConfig.full()

Creates a single-color circle configuration.

ParameterTypeDefaultDescription
fillColorColorrequiredColor of the circle's fill
borderColorColorrequiredColor of the circle's border
strokeWidthdouble16.0Width of the inner stroke
borderWidthdouble20.0Width of the outer border
baseColorColorColors.transparentBackground color

CirclePainterConfig.segmented()

Creates a multi-segment circle configuration.

ParameterTypeDefaultDescription
segmentsIterable<CircleSegment>requiredList of circle segments
strokeWidthdouble16.0Width of segment strokes
borderWidthdouble20.0Width of segment borders
baseColorColorColors.transparentBackground color
separatorAngledouble0.18Angle between segments (radians)

CircleSegment

Defines individual segments in a multi-segment circle.

PropertyTypeDescription
fillColorColorColor of the segment's fill
borderColorColorColor of the segment's border
ratiodoublePortion of circle (0.0 to 1.0)

Important: The sum of all segment ratios must equal 1.0.

PieChartPainterConfig

Configuration class that defines the visual appearance and data for pie charts.

ParameterTypeDefaultDescription
dataList<PieData>requiredList of pie data entries defining values and colors
strokeWidthdouble2.0Width of stroke outline around slices
strokeColorColorColors.whiteColor of stroke outline around slices
separatorAngledouble0.02Angle between slices (radians)
startAngledouble-π/2Starting angle for first slice (12 o'clock)

PieData

Defines individual data entries in a pie chart.

PropertyTypeDescription
valuedoubleNumeric value (must be non-negative)
colorColorFill color of the pie slice
labelString?Optional label for legends/tooltips

Note: Pie slice proportions are automatically calculated based on the ratio of each value to the total sum.

🎨 Design Patterns & Use Cases

Progress Indicators

// Simple progress bar alternative
AnimatedCircleView(
  circlePainterConfig: CirclePainterConfig.full(
    fillColor: Theme.of(context).primaryColor,
    borderColor: Theme.of(context).primaryColor.withOpacity(0.3),
  ),
)

Data Visualization

// Segmented circle for statistics
AnimatedCircleView(
  circlePainterConfig: CirclePainterConfig.segmented(
    segments: [
      CircleSegment(fillColor: Colors.blue, borderColor: Colors.blue.shade700, ratio: 0.45),   // 45%
      CircleSegment(fillColor: Colors.green, borderColor: Colors.green.shade700, ratio: 0.30), // 30%
      CircleSegment(fillColor: Colors.orange, borderColor: Colors.orange.shade700, ratio: 0.25), // 25%
    ],
  ),
)

// Filled pie chart for data representation
AnimatedPieChartView(
  pieChartPainterConfig: PieChartPainterConfig(
    data: [
      PieData(value: 450, color: Colors.blue, label: 'Sales'),
      PieData(value: 300, color: Colors.green, label: 'Marketing'),
      PieData(value: 250, color: Colors.orange, label: 'Development'),
    ],
    strokeWidth: 1.5,
    separatorAngle: 0.01,
  ),
)

Loading Indicators

// Elegant loading spinner
AnimatedCircleView(
  circlePainterConfig: CirclePainterConfig.full(
    fillColor: Colors.blue.withOpacity(0.7),
    borderColor: Colors.blue,
    strokeWidth: 8.0,
    borderWidth: 12.0,
  ),
  duration: const Duration(milliseconds: 1000),
  curve: Curves.easeInOut,
)

🔧 Performance Considerations

  • Efficient Rendering: Uses RepaintBoundary for optimized painting
  • Memory Management: Automatic cleanup of animation controllers and listeners
  • Viewport Optimization: Scroll-triggered animations only activate when visible

🐛 Troubleshooting

Common Issues

Segments don't add up to full circle

// ❌ This will throw an assertion error
CirclePainterConfig.segmented(
  segments: [
    CircleSegment(ratio: 0.5, ...),
    CircleSegment(ratio: 0.3, ...), // Total = 0.8, not 1.0
  ],
);

// ✅ Correct usage
CirclePainterConfig.segmented(
  segments: [
    CircleSegment(ratio: 0.7, ...),
    CircleSegment(ratio: 0.3, ...), // Total = 1.0
  ],
);

Animation not triggering with scroll controller

  • Ensure the ScrollController is properly attached to your scrollable widget
  • Check that the circle widget is actually within the scrollable area
  • Verify that at least 30% of the circle is visible before animation triggers

Performance issues with many circles

  • Use RepaintBoundary around individual circles when rendering many
  • Consider using ListView.builder instead of ListView for better performance
  • Implement lazy loading for large datasets

📱 Example App

This package includes a comprehensive example application demonstrating all features:

cd example
flutter run

The example showcases:

  • Full Circle Demo: Basic circular progress indicators
  • Segmented Circle Demo: Multi-colored data visualization with stroke-based segments
  • Pie Chart Demo: Filled pie charts with multiple styling options
  • Scroll Demo: Scroll-triggered animations for both circles and pie charts
  • Performance Demo: Multiple animated components with optimized rendering

🤝 Contributing

We welcome contributions! Please see our Contributing Guide for details.

Development Setup

  1. Fork the repository
  2. Clone your fork:
    git clone https://github.com/yourusername/flutter_animated_circle.git
    cd flutter_animated_circle
    
  3. Install dependencies:
    flutter pub get
    cd example && flutter pub get
    
  4. Run tests:
    flutter test
    
  5. Run the example:
    cd example && flutter run
    

Code Quality

This project maintains high code quality standards:

  • Linting: Uses very_good_analysis for strict code analysis
  • Testing: Comprehensive test coverage for all components
  • Documentation: Extensive inline documentation and examples
  • Type Safety: Full null safety support

🔄 Migration Guide

From v0.0.3 to v0.1.0

No breaking changes. This release adds major new functionality:

  • New Feature: AnimatedPieChartView widget for filled pie charts
  • New Model: PieData class for representing pie chart data
  • New Painter: PieChartPainterConfig and PieChartPainter for pie chart rendering
  • Enhanced example app with pie chart demonstrations
  • Comprehensive test coverage for new components
  • Updated documentation with pie chart examples

From v0.0.2 to v0.0.3

No breaking changes. Previous release added:

  • Enhanced documentation
  • Additional usage examples
  • Performance improvements
  • Better error handling

📊 Changelog

See CHANGELOG.md for a detailed list of changes in each version.

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

Made with Flutter 💙