import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage>
    with SingleTickerProviderStateMixin {
  AnimationController controller;

  @override
  void initState() {
    super.initState();
    controller = AnimationController(
      duration: Duration(seconds: 1),
      vsync: this,
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.grey,
      appBar: AppBar(
        title: Text('Home Page'),
      ),
      body: Center(
        child: AnimatedArrowIcon(
          controller: controller,
          color: Colors.white,
          size: Size(600, 600),
          iconSize: 30,
          onDoubleTap: () {
            controller.forward();
          },
        ),
      ),
    );
  }
}

class AnimatedArrowIcon extends StatefulWidget {
  final AnimationController controller;
  final Color color;
  final Function onTap;
  final Function onDoubleTap;
  final Size size;
  final double iconSize;

  final Animation<double> _oneIconOpacityAnimation;
  final Animation<double> _twoIconOpacityAnimation;
  final Animation<double> _threeIconOpacityAnimation;
  final Animation<Size> _sizeAnimation;

  static final double _begin = 0.0;
  static final double _end = 2.0;
  static final Curve _curve = Curves.easeInOut;

  AnimatedArrowIcon({
    Key key,
    @required this.controller,
    this.color = Colors.black,
    this.onTap,
    this.onDoubleTap,
    this.size = const Size(300, 300),
    this.iconSize = 24.0,
  })  : _oneIconOpacityAnimation =
            Tween<double>(begin: _begin, end: _end).animate(
          CurvedAnimation(
            parent: controller,
            curve: Interval(0.0, 0.7, curve: _curve),
          ),
        ),
        _twoIconOpacityAnimation =
            Tween<double>(begin: _begin, end: _end).animate(
          CurvedAnimation(
            parent: controller,
            curve: Interval(0.2, 0.8, curve: _curve),
          ),
        ),
        _threeIconOpacityAnimation =
            Tween<double>(begin: _begin, end: _end).animate(
          CurvedAnimation(
            parent: controller,
            curve: Interval(0.5, 1.0, curve: _curve),
          ),
        ),
        _sizeAnimation = Tween<Size>(begin: Size(0, 0), end: size).animate(
          CurvedAnimation(
            parent: controller,
            curve: Interval(0.0, 0.8, curve: _curve),
          ),
        ),
        super(key: key);
  @override
  _AnimatedArrowIconState createState() => _AnimatedArrowIconState();
}

class _AnimatedArrowIconState extends State<AnimatedArrowIcon> {
  double get _oneValue => _edge(_lerp(widget._oneIconOpacityAnimation.value));
  double get _twoValue => _edge(_lerp(widget._twoIconOpacityAnimation.value));
  double get _threeValue =>
      _edge(_lerp(widget._threeIconOpacityAnimation.value));

  double _edge(double v) => v > 1.0 ? 1.0 : v < 0 ? 0 : v;
  double _lerp(double v) => v >= 1 ? (v - AnimatedArrowIcon._end).abs() : v;

  double _opacity = 0;

  @override
  void initState() {
    super.initState();
    widget.controller.addStatusListener((status) {
      if (status == AnimationStatus.completed) {
        setState(() => _opacity = 0);
        widget.controller.reset();
      }

      if (status == AnimationStatus.forward) {
        setState(() => _opacity = 1);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: widget.onTap,
      onDoubleTap: widget.onDoubleTap,
      child: AnimatedBuilder(
        animation: widget.controller,
        builder: (context, child) {
          return Stack(
            alignment: Alignment.center,
            children: [
              AnimatedOpacity(
                opacity: _opacity,
                duration: widget.controller.duration,
                curve: Curves.easeOutQuint,
                child: Container(
                  width: widget.size.width,
                  height: widget.size.width,
                  decoration: BoxDecoration(
                    shape: BoxShape.circle,
                    color: Colors.white.withOpacity(0.1),
                  ),
                ),
              ),
              Container(
                width: widget._sizeAnimation.value.width,
                height: widget._sizeAnimation.value.height,
                decoration: BoxDecoration(
                  shape: BoxShape.circle,
                  color: Colors.white.withOpacity(0.1),
                ),
              ),
              SizedBox(
                width: widget.iconSize * 3.0,
                child: Stack(
                  alignment: Alignment.center,
                  children: [
                    Align(
                      alignment: Alignment(-0.6, 0),
                      child: Opacity(
                        opacity: _oneValue,
                        child: child,
                      ),
                    ),
                    Opacity(
                      opacity: _twoValue,
                      child: child,
                    ),
                    Align(
                      alignment: Alignment(0.6, 0),
                      child: Opacity(
                        opacity: _threeValue,
                        child: child,
                      ),
                    ),
                  ],
                ),
              ),
            ],
          );
        },
        child: Icon(
          Icons.play_arrow,
          color: widget.color,
          size: widget.iconSize,
        ),
      ),
    );
  }
}
02-14 04:13