OverLoadedBurden
OverLoadedBurden

Reputation: 734

How to chain multiple Animation objects?

What i want is to chain multiple Animation object like if we have an Animation<double> that goes from 0 to 40 (let's call it the big one) and i have another 4 Animation<double> object what i want is

  1. when the big animation starts the first animation start with it , but it end's when the big one reach 10.
  2. when the big one reach 10 the second animation start's and end's when the big one reach 20. etc...

any one knows how to do it in flutter ??

Upvotes: 4

Views: 11965

Answers (1)

ZlatiP
ZlatiP

Reputation: 205

It sounds like staggered animations. Basically, you can create an animation controller and set the total duration time. Then, you can create a separate tween for each animation you want to perform. For each tween, you can define a curve, for that curve you can define an interval in the percentage of the total duration of the animation. There is a pretty good example in a flutter.dev when you search for staggered animations. Note: they don't have to be one after another, despite the name, they can be fired at the same time, but end at different time as you want. I'm not sure if it is appropriate to give an answer with just sharing the link to the flutter docs, but here it is https://flutter.dev/docs/development/ui/animations/staggered-animations. I have done something similar, but with 2 controllers, which I fire at the same time, but they have different durations.

Ah, I was second :)

edit: here is some code one with 2 controlers

import 'package:flutter/material.dart';
//import 'package:flutter/scheduler.dart';
import 'package:flutter_color_picker/components/color_ripple.dart';

class ColorKnob extends StatefulWidget {
  const ColorKnob({this.color, this.ratio, this.saveColor});

  final Color color;
  final double ratio;
  final Function saveColor;

  @override
  _ColorKnobState createState() => _ColorKnobState();
}

class _ColorKnobState extends State<ColorKnob> with TickerProviderStateMixin {
  AnimationController scaleAnimationController;
  AnimationController rippleAnimationController;
  Animation<double> scaleAnimation;

  @override
  void initState() {
    super.initState();
    scaleAnimationController =
        AnimationController(vsync: this, duration: Duration(milliseconds: 100));

    rippleAnimationController =
        AnimationController(vsync: this, duration: Duration(milliseconds: 400));

    scaleAnimationController.addStatusListener((AnimationStatus status) {
      if (status == AnimationStatus.completed) {
        scaleAnimationController.reverse();
      }
    });

    scaleAnimation = Tween<double>(begin: 1.0, end: 0.8).animate(
        CurvedAnimation(
            parent: scaleAnimationController, curve: Curves.easeOut));

    rippleAnimationController.addStatusListener((AnimationStatus status) {
      if (status == AnimationStatus.completed) {
        widget.saveColor();
      }
    });

    scaleAnimation.addListener(() {
      setState(() {});
    });
  }

  @override
  void dispose() {
    super.dispose();
    scaleAnimationController.dispose();
    rippleAnimationController.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
          decoration: const BoxDecoration(
              shape: BoxShape.circle, color: Colors.transparent),
          child: FractionallySizedBox(
            widthFactor: widget.ratio,
            heightFactor: widget.ratio,
            child: ClipOval(
              clipBehavior: Clip.antiAlias,
              child: Center(
                child: Stack(children: <Widget>[
                  ColorRipple(
                      controller: rippleAnimationController,
                      color: widget.color,
                  ),
                  GestureDetector(
                    onTap: () {
                      //            timeDilation = 1.0;
                      scaleAnimationController.forward(from: 0.0);
                      rippleAnimationController.forward(from: 0.0);
                    },
                    child: Transform.scale(
                      scale: scaleAnimation.value,
                      alignment: Alignment.center,
                      child: Container(
                        width: 60.0,
                        height: 60.0,
                        decoration: BoxDecoration(
                            shape: BoxShape.circle,
                            color: widget.color,
                            border: Border.all(
                              color: const Color(0xFFFFFFFF),
                              style: BorderStyle.solid,
                              width: 4.0,
                            ),
                            boxShadow: const <BoxShadow>[
                              BoxShadow(
                                offset: Offset(0.0, 1.0),
                                blurRadius: 6.0,
                                spreadRadius: 1.0,
                                color: Color(0x44000000),
                              )
                            ]),
                      ),
                    ),
                  ),
                ]),
              ),
            ),
          )),
    );
  }
}

and one with multiple tweens

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

class ColorRipple extends StatelessWidget {
  ColorRipple({this.controller, this.color, this.size})
      : scaleUpAnimation = Tween<double>(begin: 0.8, end: 5.0).animate(
          CurvedAnimation(
            parent: controller,
            curve: const Interval(
              0.2,
              1.0,
              curve: Cubic(0.25, 0.46, 0.45, 0.94),
            ),
          ),
        ),
        opacityAnimation = Tween<double>(begin: 0.6, end: 0.0).animate(
          CurvedAnimation(
            parent: controller,
            curve: const Interval(
              0.4,
              1.0,
              curve: Cubic(0.25, 0.46, 0.45, 0.94),
            ),
          ),
        ),
        scaleDownAnimation = Tween<double>(begin: 1.0, end: 0.8).animate(
          CurvedAnimation(
            parent: controller,
            curve: const Interval(0.0, 0.2, curve: Curves.easeOut),
          ),
        );

  final AnimationController controller;
  final Animation<double> scaleUpAnimation;
  final Animation<double> scaleDownAnimation;
  final Animation<double> opacityAnimation;
  final Color color;
  final Size size;

  @override
  Widget build(BuildContext context) {
    return AnimatedBuilder(
        animation: controller,
        builder: (BuildContext context, Widget child) {
          return Container(
            child: Transform(
              alignment: Alignment.center,
              transform: Matrix4.identity()
                ..scale(scaleDownAnimation.value)
                ..scale(scaleUpAnimation.value),
              child: Opacity(
                  opacity: opacityAnimation.value,
                  child: Container(
                    width: 60.0,
                    height: 60.0,
                    decoration: BoxDecoration(
                        shape: BoxShape.circle,
                        border: Border.all(
                            color: color,
                            style: BorderStyle.solid,
                            width: 4.0 - (2 * controller.value))),
                  )),
            ),
          );
        });
  }
}

Upvotes: 7

Related Questions