{"id":13551946,"url":"https://github.com/felixblaschke/simple_animations","last_synced_at":"2025-05-15T15:06:42.027Z","repository":{"id":37549829,"uuid":"178591159","full_name":"felixblaschke/simple_animations","owner":"felixblaschke","description":"Flutter package for creating awesome animations.","archived":false,"fork":false,"pushed_at":"2025-05-03T10:52:00.000Z","size":5654,"stargazers_count":1049,"open_issues_count":0,"forks_count":107,"subscribers_count":15,"default_branch":"main","last_synced_at":"2025-05-03T11:32:42.599Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/felixblaschke.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-03-30T17:38:22.000Z","updated_at":"2025-05-03T10:49:27.000Z","dependencies_parsed_at":"2024-01-05T21:04:47.208Z","dependency_job_id":null,"html_url":"https://github.com/felixblaschke/simple_animations","commit_stats":{"total_commits":226,"total_committers":4,"mean_commits":56.5,"dds":0.02212389380530977,"last_synced_commit":"8356606b2c85982dc920ab55439fc8e8f50391ec"},"previous_names":[],"tags_count":46,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felixblaschke%2Fsimple_animations","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felixblaschke%2Fsimple_animations/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felixblaschke%2Fsimple_animations/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/felixblaschke%2Fsimple_animations/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/felixblaschke","download_url":"https://codeload.github.com/felixblaschke/simple_animations/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254364270,"owners_count":22058878,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T12:01:56.214Z","updated_at":"2025-05-15T15:06:41.997Z","avatar_url":"https://github.com/felixblaschke.png","language":"Dart","funding_links":[],"categories":["框架","Dart","Animation [🔝](#readme)","Frameworks"],"sub_categories":["动画","Animation"],"readme":"\u003c!-- This file uses generated code. Visit https://pub.dev/packages/readme_helper for usage information. --\u003e\n\n# 🎬 Simple Animations\n\n[![Pub](https://img.shields.io/pub/v/simple_animations.svg)](https://pub.dartlang.org/packages/simple_animations)\n[![Awesome Flutter](https://img.shields.io/badge/Awesome-Flutter-blue)](https://github.com/Solido/awesome-flutter)\n[![Flutter gems - Top 5 Animation packages](https://img.shields.io/badge/Flutter%20gems-TOP%205%20Animation%20packages-blue)](https://fluttergems.dev/animation-transition/)\n\n**Simple Animations** simplifies the process of creating beautiful custom animations:\n\n- Easily create **custom animations in stateless widgets**\n- Animate **multiple properties** at once\n- Create **staggered animations** within seconds\n- Simplified working with **AnimationController** instances\n- Debug animations\n\n\u003c!-- #toc --\u003e\n## Table of Contents\n\n[**Quickstart**](#quickstart)\n  - [Animation Builder - Quickstart](#animation-builder---quickstart)\n  - [Movie Tween - Quickstart](#movie-tween---quickstart)\n  - [Animation Mixin - Quickstart](#animation-mixin---quickstart)\n  - [Animation Developer Tools - Quickstart](#animation-developer-tools---quickstart)\n\n[**Animation Builder**](#animation-builder)\n  - [Essential parts of the animation](#essential-parts-of-the-animation)\n  - [PlayAnimationBuilder](#playanimationbuilder)\n  - [LoopAnimationBuilder](#loopanimationbuilder)\n  - [MirrorAnimationBuilder](#mirroranimationbuilder)\n  - [CustomAnimationBuilder](#customanimationbuilder)\n\n[**Movie Tween**](#movie-tween)\n  - [Basic usage pattern](#basic-usage-pattern)\n  - [Scenes](#scenes)\n  - [Animate properties](#animate-properties)\n  - [Curves](#curves)\n  - [Extrapolation](#extrapolation)\n  - [Use developer tools](#use-developer-tools)\n  - [Animation duration](#animation-duration)\n\n[**Animation Mixin**](#animation-mixin)\n  - [Basic usage pattern](#basic-usage-pattern)\n  - [Create multiple AnimationController](#create-multiple-animationcontroller)\n\n[**Shortcuts for AnimationController**](#shortcuts-for-animationcontroller)\n\n[**Animation Developer Tools**](#animation-developer-tools)\n  - [Basic usage pattern](#basic-usage-pattern)\n  - [Features and tricks](#features-and-tricks)\n\u003c!-- // end of #toc --\u003e\n\n## Quickstart\n\nDirectly dive in and let the code speak for itself.\n\n### Animation Builder - Quickstart\n\nAnimation Builder are powerful widgets to easily create custom animations.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/animation_builder.dart --\u003e\n```dart\nimport 'dart:math';\n\nimport 'package:flutter/material.dart';\nimport 'package:simple_animations/simple_animations.dart';\n\nclass ResizeCubeAnimation extends StatelessWidget {\n  const ResizeCubeAnimation({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    // PlayAnimationBuilder plays animation once\n    return PlayAnimationBuilder\u003cdouble\u003e(\n      tween: Tween(begin: 100.0, end: 200.0), // 100.0 to 200.0\n      duration: const Duration(seconds: 1), // for 1 second\n      builder: (context, value, _) {\n        return Container(\n          width: value, // use animated value\n          height: value,\n          color: Colors.blue,\n        );\n      },\n      onCompleted: () {\n        // do something ...\n      },\n    );\n  }\n}\n\nclass RotatingBox extends StatelessWidget {\n  const RotatingBox({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    // LoopAnimationBuilder plays forever: from beginning to end\n    return LoopAnimationBuilder\u003cdouble\u003e(\n      tween: Tween(begin: 0.0, end: 2 * pi), // 0° to 360° (2π)\n      duration: const Duration(seconds: 2), // for 2 seconds per iteration\n      builder: (context, value, _) {\n        return Transform.rotate(\n          angle: value, // use value\n          child: Container(color: Colors.blue, width: 100, height: 100),\n        );\n      },\n    );\n  }\n}\n\nclass ColorFadeLoop extends StatelessWidget {\n  const ColorFadeLoop({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    // MirrorAnimationBuilder plays forever: alternating forward and backward\n    return MirrorAnimationBuilder\u003cColor?\u003e(\n      tween: ColorTween(begin: Colors.red, end: Colors.blue), // red to blue\n      duration: const Duration(seconds: 5), // for 5 seconds per iteration\n      builder: (context, value, _) {\n        return Container(\n          color: value, // use animated value\n          width: 100,\n          height: 100,\n        );\n      },\n    );\n  }\n}\n```\n\u003c!-- // end of #code --\u003e\n\n[**Read guide**](#animation-builder) or [**watch examples**](example/example.md#animation-builder).\n\n---\n\n### Movie Tween - Quickstart\n\nMovie Tween combines multiple tween into one, including timeline control and value extrapolation.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/movie_tween.dart --\u003e\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:simple_animations/simple_animations.dart';\n\n// Simple staggered tween\nfinal tween1 = MovieTween()\n  ..tween('width', Tween(begin: 0.0, end: 100),\n          duration: const Duration(milliseconds: 1500), curve: Curves.easeIn)\n      .thenTween('width', Tween(begin: 100, end: 200),\n          duration: const Duration(milliseconds: 750), curve: Curves.easeOut);\n\n// Design tween by composing scenes\nfinal tween2 = MovieTween()\n  ..scene(\n          begin: const Duration(milliseconds: 0),\n          duration: const Duration(milliseconds: 500))\n      .tween('width', Tween\u003cdouble\u003e(begin: 0.0, end: 400.0))\n      .tween('height', Tween\u003cdouble\u003e(begin: 500.0, end: 200.0))\n      .tween('color', ColorTween(begin: Colors.red, end: Colors.blue))\n  ..scene(\n          begin: const Duration(milliseconds: 700),\n          end: const Duration(milliseconds: 1200))\n      .tween('width', Tween\u003cdouble\u003e(begin: 400.0, end: 500.0));\n\n// Type-safe alternative\nfinal width = MovieTweenProperty\u003cdouble\u003e();\nfinal color = MovieTweenProperty\u003cColor?\u003e();\n\nfinal tween3 = MovieTween()\n  ..tween\u003cdouble\u003e(width, Tween(begin: 0.0, end: 100))\n  ..tween\u003cColor?\u003e(color, ColorTween(begin: Colors.red, end: Colors.blue));\n```\n\u003c!-- // end of #code --\u003e\n\n[**Read guide**](#movie-tween) or [**watch examples**](example/example.md#movie-tween).\n\n---\n\n### Animation Mixin - Quickstart\n\nThe **Animation Mixin** manages `AnimationController` instances for you.\nNo more boilerplate code.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/animation_mixin.dart --\u003e\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:simple_animations/simple_animations.dart';\n\nclass MyWidget extends StatefulWidget {\n  const MyWidget({super.key});\n\n  @override\n  _MyWidgetState createState() =\u003e _MyWidgetState();\n}\n\n// Add AnimationMixin\nclass _MyWidgetState extends State\u003cMyWidget\u003e with AnimationMixin {\n  late Animation\u003cdouble\u003e size;\n\n  @override\n  void initState() {\n    // The AnimationController instance `controller` is already wired up.\n    // Just connect with it with the tweens.\n    size = Tween\u003cdouble\u003e(begin: 0.0, end: 200.0).animate(controller);\n\n    controller.play(); // start the animation playback\n\n    super.initState();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Container(\n      width: size.value, // use animated value\n      height: size.value,\n      color: Colors.red,\n    );\n  }\n}\n```\n\u003c!-- // end of #code --\u003e\n\n[**Read guide**](#animation-mixin) or [**watch examples**](example/example.md#animation-mixin).\n\n---\n\n### Animation Developer Tools - Quickstart\n\nHelps you fine tuning the animation. It allows you to pause anywhere, scroll around, speed up, slow down or focus on a certain part of the animation.\n\n![devtools](https://github.com/felixblaschke/simple_animations/raw/main/example/img/d1.gif)\n\n[**Read guide**](#animation-developer-tools)\n\n\u0026nbsp;\n\n## Animation Builder\n\nAnimation Builder enables developers to craft custom animations with simple widgets.\n\n### Essential parts of the animation\n\nYou need three things to create an animation:\n\n- **tween**: What _value_ is changing within the animation?\n- **duration**: How long does the animation take?\n- **builder**: How does the UI look like regarding the changing _value_?\n\n#### Tween\n\nThe `tween` is the description of your animation. Mostly it will change a value from A to B. Tweens describe **what** will happen but **not how fast it will happen**.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/animation_builder/pa_tween.dart --\u003e\n```dart\nimport 'package:flutter/material.dart';\n\n// Animate a color from red to blue\nvar colorTween = ColorTween(begin: Colors.red, end: Colors.blue);\n\n// Animate a double value from 0 to 100\nvar doubleTween = Tween\u003cdouble\u003e(begin: 0.0, end: 100.0);\n```\n\u003c!-- // end of #code --\u003e\n\nTo animate multiple properties, use a [Movie Tween](#movie-tween).\n\n#### Duration\n\nThe `duration` is the time the animation takes.\n\n#### Builder\n\nThe `builder` is a function that is called for **each new rendered frame** of your animation. It takes three parameters: `context`, `value` and `child`.\n\n- `context` is your Flutter `BuildContext`\n\n- `value` is **current value** of any animated variable, produced by the tween. If your tween is `Tween\u003cdouble\u003e(begin: 0.0, end: 100.0)`, the `value` is a `double` somewhere between `0.0` and `100.0`.\n\n- `child` can be a widget that you might pass in a Animation Builder widget. This widget stays constant and is not affected by the animation.\n\nHow often the `builder` function is called, depends on the animation duration, and the framerate of the device used.\n\n### PlayAnimationBuilder\n\nThe PlayAnimationBuilder is a widget that plays an animation once.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/animation_builder/pa_basic.dart --\u003e\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:simple_animations/simple_animations.dart';\n\n// Use type `Color?` because ColorTween produces type `Color?`\nvar widget = PlayAnimationBuilder\u003cColor?\u003e(\n  tween: ColorTween(begin: Colors.red, end: Colors.blue), // define tween\n  duration: const Duration(seconds: 5), // define duration\n  builder: (context, value, _) {\n    return Container(\n      color: value, // use animated color\n      width: 100,\n      height: 100,\n    );\n  },\n);\n```\n\u003c!-- // end of #code --\u003e\n\n#### Delay\n\nBy default, animations will play automatically. You can set a `delay` to make `PlayAnimationBuilder` wait for a given amount of time.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/animation_builder/pa_delay.dart --\u003e\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:simple_animations/simple_animations.dart';\n\nvar widget = PlayAnimationBuilder\u003cColor?\u003e(\n  tween: ColorTween(begin: Colors.red, end: Colors.blue),\n  duration: const Duration(seconds: 5),\n  delay: const Duration(seconds: 2), // add delay\n  builder: (context, value, _) {\n    return Container(\n      color: value,\n      width: 100,\n      height: 100,\n    );\n  },\n);\n```\n\u003c!-- // end of #code --\u003e\n\n#### Non-linear motion\n\nYou can make your animation more appealing by applying non-linear motion behavior to it.\nJust pass a `curve` into the widget.\n\nFlutter comes with a set of predefined curves inside the `Curves` class.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/animation_builder/pa_curve.dart --\u003e\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:simple_animations/simple_animations.dart';\n\nvar widget = PlayAnimationBuilder\u003cColor?\u003e(\n  tween: ColorTween(begin: Colors.red, end: Colors.blue),\n  duration: const Duration(seconds: 5),\n  curve: Curves.easeInOut, // specify curve\n  builder: (context, value, _) {\n    return Container(\n      color: value,\n      width: 100,\n      height: 100,\n    );\n  },\n);\n```\n\u003c!-- // end of #code --\u003e\n\n#### Animation lifecycle\n\nYou can react to the animation status by setting callbacks.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/animation_builder/pa_lifecycle.dart --\u003e\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:simple_animations/simple_animations.dart';\n\nvar widget = PlayAnimationBuilder\u003cColor?\u003e(\n  // lifecycle callbacks\n  onStarted: () =\u003e debugPrint('Animation started'),\n  onCompleted: () =\u003e debugPrint('Animation complete'),\n\n  tween: ColorTween(begin: Colors.red, end: Colors.blue),\n  duration: const Duration(seconds: 5),\n  builder: (context, value, _) =\u003e\n      Container(color: value, width: 100, height: 100),\n);\n```\n\u003c!-- // end of #code --\u003e\n\n#### Using child widgets\n\nParts of the UI that are not effected by the animated value can be passed as a `Widget` into the `child` property. That `Widget` is available within the `builder` function.\nThey will not rebuild when animated value changes and therefore has a positive performance impact.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/animation_builder/pa_child.dart --\u003e\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:simple_animations/simple_animations.dart';\n\nvar widget = PlayAnimationBuilder\u003cColor?\u003e(\n  tween: ColorTween(begin: Colors.red, end: Colors.blue),\n  duration: const Duration(seconds: 5),\n  // child gets passed into builder function\n  builder: (context, value, child) {\n    return Container(\n      color: value,\n      width: 100,\n      height: 100,\n      child: child, // use child\n    );\n  },\n  child: const Text('Hello World'), // specify child widget\n);\n```\n\u003c!-- // end of #code --\u003e\n\n#### Using keys\n\nIf Flutter swaps out a `PlayAnimationBuilder` with another different `PlayAnimationBuilder` in a rebuild, it may recycle the first one.\nThis may lead to a undesired behavior.\nIn such a case use the `key` property.\n\nYou may [watch this introduction](https://www.youtube.com/watch?v=kn0EOS-ZiIc) to `Key`.\n\n#### App example\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/animation_builder/example_play_animation.dart --\u003e\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:simple_animations/simple_animations.dart';\n\nvoid main() =\u003e runApp(\n    const MaterialApp(home: Scaffold(body: Center(child: AnimatedGreenBox()))));\n\nclass AnimatedGreenBox extends StatelessWidget {\n  const AnimatedGreenBox({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return PlayAnimationBuilder\u003cdouble\u003e(\n      // specify tween (from 50.0 to 200.0)\n      tween: Tween\u003cdouble\u003e(begin: 50.0, end: 200.0),\n\n      // set a duration\n      duration: const Duration(seconds: 5),\n\n      // set a curve\n      curve: Curves.easeInOut,\n\n      // use builder function\n      builder: (context, value, child) {\n        // apply animated value obtained from builder function parameter\n        return Container(\n          width: value,\n          height: value,\n          color: Colors.green,\n          child: child,\n        );\n      },\n      child: const Text('Hello World'),\n    );\n  }\n}\n```\n\u003c!-- // end of #code --\u003e\n\n### LoopAnimationBuilder\n\nA `LoopAnimationBuilder` repeatedly plays the animation from the start to the end over and over again.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/animation_builder/loop_animation.dart --\u003e\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:simple_animations/simple_animations.dart';\n\nvar widget = LoopAnimationBuilder\u003cColor?\u003e(\n  // mandatory parameters\n  tween: ColorTween(begin: Colors.red, end: Colors.blue),\n  duration: const Duration(seconds: 5),\n  builder: (context, value, child) {\n    return Container(color: value, width: 100, height: 100, child: child);\n  },\n  // optional parameters\n  curve: Curves.easeInOut,\n  child: const Text('Hello World'),\n);\n```\n\u003c!-- // end of #code --\u003e\n\n### MirrorAnimationBuilder\n\nA `MirrorAnimationBuilder` repeatedly plays the animation from the start to the end, then reverse to the start, then again forward and so on.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/animation_builder/mirror_animation.dart --\u003e\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:simple_animations/simple_animations.dart';\n\nvar widget = MirrorAnimationBuilder\u003cColor?\u003e(\n  // mandatory parameters\n  tween: ColorTween(begin: Colors.red, end: Colors.blue),\n  duration: const Duration(seconds: 5),\n  builder: (context, value, child) {\n    return Container(color: value, width: 100, height: 100, child: child);\n  },\n  // optional parameters\n  curve: Curves.easeInOut,\n  child: const Text('Hello World'),\n);\n```\n\u003c!-- // end of #code --\u003e\n\n### CustomAnimationBuilder\n\nUse `CustomAnimationBuilder` if the animation widgets discussed above aren't sufficient for you use case. Beside all parameters mentioned for `PlayAnimationBuilder` it allows you actively control the animation.\n\n#### Control the animation\n\nThe `control` parameter can be set to the following values:\n\n| Control.VALUE        | Description                                                                                                                |\n| -------------------- | -------------------------------------------------------------------------------------------------------------------------- |\n| `stop`               | Stops the animation at the current position.                                                                               |\n| `play`               | Plays the animation from the current position to the end.                                                                  |\n| `playReverse`        | Plays the animation from the current position reverse to the start.                                                        |\n| `playFromStart`      | Resets the animation position to the beginning (`0.0`) and starts playing to the end.                                      |\n| `playReverseFromEnd` | Resets the position of the animation to end (`1.0`) and starts playing backwards to the start.                             |\n| `loop`               | Endlessly plays the animation from the start to the end.                                                                   |\n| `mirror`             | Endlessly plays the animation from the start to the end, then it plays reverse to the start, then forward again and so on. |\n\nYou can bind the `control` value to state variable and change it during the animation. The `CustomAnimationBuilder` will adapt to that.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/animation_builder/example_control.dart --\u003e\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:simple_animations/simple_animations.dart';\n\nvoid main() =\u003e runApp(\n    const MaterialApp(home: Scaffold(body: Center(child: SwappingButton()))));\n\nclass SwappingButton extends StatefulWidget {\n  const SwappingButton({super.key});\n\n  @override\n  _SwappingButtonState createState() =\u003e _SwappingButtonState();\n}\n\nclass _SwappingButtonState extends State\u003cSwappingButton\u003e {\n  var control = Control.play; // define variable\n\n  void _toggleDirection() {\n    setState(() {\n      // let the animation play to the opposite direction\n      control = control == Control.play ? Control.playReverse : Control.play;\n    });\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return CustomAnimationBuilder\u003cdouble\u003e(\n      control: control, // bind variable with control instruction\n      tween: Tween\u003cdouble\u003e(begin: -100.0, end: 100.0),\n      duration: const Duration(seconds: 1),\n      builder: (context, value, child) {\n        // moves child from left to right\n        return Transform.translate(\n          offset: Offset(value, 0),\n          child: child,\n        );\n      },\n      child: OutlinedButton(\n        // clicking button changes animation direction\n        onPressed: _toggleDirection,\n        child: const Text('Swap'),\n      ),\n    );\n  }\n}\n```\n\u003c!-- // end of #code --\u003e\n\n#### Start position\n\nBy default the animation starts from the beginning (`0.0`). You can change this by setting the `startPosition` parameter. It can be set to a value between `0.0` (beginning) and `1.0` (end).\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/animation_builder/start_position.dart --\u003e\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:simple_animations/simple_animations.dart';\n\nvar widget = CustomAnimationBuilder\u003cColor?\u003e(\n  control: Control.play,\n  startPosition: 0.5, // set start position at 50%\n  duration: const Duration(seconds: 5),\n  tween: ColorTween(begin: Colors.red, end: Colors.blue),\n  builder: (context, value, child) {\n    return Container(color: value, width: 100, height: 100);\n  },\n);\n```\n\u003c!-- // end of #code --\u003e\n\n#### Animation lifecycle\n\nYou can react to the animation status by setting callbacks.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/animation_builder/ca_lifecycle.dart --\u003e\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:simple_animations/simple_animations.dart';\n\nvar widget = CustomAnimationBuilder\u003cColor?\u003e(\n  // lifecycle callbacks\n  onStarted: () =\u003e debugPrint('Animation started'),\n  onCompleted: () =\u003e debugPrint('Animation complete'),\n\n  tween: ColorTween(begin: Colors.red, end: Colors.blue),\n  duration: const Duration(seconds: 5),\n  builder: (context, value, child) {\n    return Container(color: value, width: 100, height: 100);\n  },\n);\n```\n\u003c!-- // end of #code --\u003e\n\nIt's also possible to directly access the `AnimationStatusListener` of the internal `AnimationController`.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/animation_builder/animation_status.dart --\u003e\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:simple_animations/simple_animations.dart';\n\nvar widget = CustomAnimationBuilder\u003cColor?\u003e(\n  animationStatusListener: (AnimationStatus status) {\n    // provide listener\n    if (status == AnimationStatus.completed) {\n      debugPrint('Animation completed!');\n    }\n  },\n  tween: ColorTween(begin: Colors.red, end: Colors.blue),\n  duration: const Duration(seconds: 5),\n  builder: (context, value, child) {\n    return Container(color: value, width: 100, height: 100);\n  },\n);\n```\n\u003c!-- // end of #code --\u003e\n\n\u0026nbsp;\n\n## Movie Tween\n\nMovie Tween combines multiple tween into one, including timeline control and value extrapolation.\n\n### Basic usage pattern\n\nCreate a new `MovieTween` and use the `tween()` to tween multiples values:\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/movie_tween/basic1.dart --\u003e\n```dart\nfinal tween = MovieTween();\n\ntween.tween('width', Tween(begin: 0.0, end: 100.0),\n    duration: const Duration(milliseconds: 700));\n\ntween.tween('height', Tween(begin: 100.0, end: 200.0),\n    duration: const Duration(milliseconds: 700));\n```\n\u003c!-- // end of #code --\u003e\n\nYou can use `..` to get a nice builder style syntax:\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/movie_tween/basic1_builder.dart --\u003e\n```dart\nfinal tween = MovieTween()\n  ..tween('width', Tween(begin: 0.0, end: 100.0),\n      duration: const Duration(milliseconds: 700))\n  ..tween('height', Tween(begin: 100.0, end: 200.0),\n      duration: const Duration(milliseconds: 700));\n```\n\u003c!-- // end of #code --\u003e\n\nIn order to not repeat yourself, you can use `scene()` to create an explicit scene and apply both tween to it:\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/movie_tween/basic2.dart --\u003e\n```dart\nfinal tween = MovieTween();\n\ntween.scene(duration: const Duration(milliseconds: 700))\n  ..tween('width', Tween(begin: 0.0, end: 100.0))\n  ..tween('height', Tween(begin: 100.0, end: 200.0));\n```\n\u003c!-- // end of #code --\u003e\n\nCalling `tween()` creates a scene as well. Therefore you can just call `thenTween()` to create staggered animations.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/movie_tween/basic3.dart --\u003e\n```dart\nfinal tween = MovieTween();\n\ntween\n    .tween('width', Tween(begin: 0.0, end: 100.0),\n        duration: const Duration(milliseconds: 700))\n    .thenTween('width', Tween(begin: 100.0, end: 200.0),\n        duration: const Duration(milliseconds: 500));\n```\n\u003c!-- // end of #code --\u003e\n\nYou can use e.g. a `PlayAnimationBuilder` to bring the `MovieTween` alive:\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/movie_tween/play_animation_example.dart --\u003e\n```dart\n@override\nWidget build(BuildContext context) {\n  // create tween\n  var tween = MovieTween()\n    ..scene(duration: const Duration(milliseconds: 700))\n        .tween('width', Tween\u003cdouble\u003e(begin: 0.0, end: 100.0))\n        .tween('height', Tween\u003cdouble\u003e(begin: 300.0, end: 200.0));\n\n  return PlayAnimationBuilder\u003cMovie\u003e(\n    tween: tween, // provide tween\n    duration: tween.duration, // total duration obtained from MovieTween\n    builder: (context, value, _) {\n      return Container(\n        width: value.get('width'), // get animated width value\n        height: value.get('height'), // get animated height value\n        color: Colors.yellow,\n      );\n    },\n  );\n}\n```\n\u003c!-- // end of #code --\u003e\n\n`MovieTween` animates to `Movie` that offers you a `get()` method to obtain a single animated value.\n\n### Scenes\n\nA `MovieTween` can consist of multiple scenes with each scene having multiple tweened properties. Those scenes can be created\n\n- implicitly using `tween()` or `thenTween()`,\n- explicitly using `scene()` or `thenFor()`.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/movie_tween/scenes.dart --\u003e\n```dart\nfinal tween = MovieTween();\n\n// implicit scenes\nfinal sceneA1 = tween.tween('x', Tween(begin: 0.0, end: 1.0),\n    duration: const Duration(milliseconds: 700));\n\nfinal sceneA2 = sceneA1.thenTween('x', Tween(begin: 1.0, end: 2.0),\n    duration: const Duration(milliseconds: 500));\n\n// explicit scenes\nfinal sceneB1 = tween\n    .scene(duration: const Duration(milliseconds: 700))\n    .tween('x', Tween(begin: 0.0, end: 1.0));\n\nfinal sceneB2 = sceneA1\n    .thenFor(duration: const Duration(milliseconds: 500))\n    .tween('x', Tween(begin: 1.0, end: 2.0));\n```\n\u003c!-- // end of #code --\u003e\n\n#### Absolute scenes\n\nYou can add scenes anywhere in the timeline of your tween by using `tween.scene()`. You just need to provide two of these parameters:\n\n- `begin` (start time of the scene)\n- `duration` (duration of the scene)\n- `end` (end time of the scene)\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/movie_tween/scenes_absolute.dart --\u003e\n```dart\nfinal tween = MovieTween();\n\n// start at 0ms and end at 1500ms\nfinal scene1 = tween.scene(\n  duration: const Duration(milliseconds: 1500),\n);\n\n// start at 200ms and end at 900ms\nfinal scene2 = tween.scene(\n  begin: const Duration(milliseconds: 200),\n  duration: const Duration(milliseconds: 700),\n);\n\n// start at 700ms and end at 1400ms\nfinal scene3 = tween.scene(\n  begin: const Duration(milliseconds: 700),\n  end: const Duration(milliseconds: 1400),\n);\n\n// start at 1000ms and end at 1600ms\nfinal scene4 = tween.scene(\n  duration: const Duration(milliseconds: 600),\n  end: const Duration(milliseconds: 1600),\n);\n```\n\u003c!-- // end of #code --\u003e\n\n#### Relative scenes\n\nYou can also make scenes depend on each other by using `thenFor()`.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/movie_tween/scenes_relative.dart --\u003e\n```dart\nfinal tween = MovieTween();\n\nfinal firstScene = tween\n    .scene(\n      begin: const Duration(seconds: 0),\n      duration: const Duration(seconds: 2),\n    )\n    .tween('x', ConstantTween\u003cint\u003e(0));\n\n// secondScene references the firstScene\nfinal secondScene = firstScene\n    .thenFor(\n      delay: const Duration(milliseconds: 200),\n      duration: const Duration(seconds: 2),\n    )\n    .tween('x', ConstantTween\u003cint\u003e(1));\n```\n\u003c!-- // end of #code --\u003e\n\nIt also possible to add an optional `delay` to add further time between the scenes.\n\n#### Hint on code style\n\nBy using builder style Dart syntax and comments you can easily create a well-readable animation.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/movie_tween/tween.dart --\u003e\n```dart\nMovieTween()\n\n    /// fade in\n    .scene(\n      begin: const Duration(seconds: 0),\n      duration: const Duration(milliseconds: 300),\n    )\n    .tween('x', Tween\u003cdouble\u003e(begin: 0.0, end: 100.0))\n    .tween('y', Tween\u003cdouble\u003e(begin: 0.0, end: 200.0))\n\n    /// grow\n    .thenFor(duration: const Duration(milliseconds: 700))\n    .tween('x', Tween\u003cdouble\u003e(begin: 100.0, end: 200.0))\n    .tween('y', Tween\u003cdouble\u003e(begin: 200.0, end: 400.0))\n\n    /// fade out\n    .thenFor(duration: const Duration(milliseconds: 300))\n    .tween('x', Tween\u003cdouble\u003e(begin: 200.0, end: 0.0))\n    .tween('y', Tween\u003cdouble\u003e(begin: 400.0, end: 0.0));\n```\n\u003c!-- // end of #code --\u003e\n\n### Animate properties\n\nYou can use `tween()` to specify a tween for single property.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/movie_tween/animate1.dart --\u003e\n```dart\nfinal tween = MovieTween();\nfinal scene = tween.scene(end: const Duration(seconds: 1));\n\nscene.tween('width', Tween(begin: 0.0, end: 100.0));\nscene.tween('color', ColorTween(begin: Colors.red, end: Colors.blue));\n```\n\u003c!-- // end of #code --\u003e\n\nYou can fine tune the timing with `shiftBegin` or `shiftEnd` for each property.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/movie_tween/animate2.dart --\u003e\n```dart\nscene.tween('width', Tween(begin: 0.0, end: 100.0),\n    shiftBegin: const Duration(milliseconds: 200), // start later\n    shiftEnd: const Duration(milliseconds: -200) // end earlier\n    );\n```\n\u003c!-- // end of #code --\u003e\n\n### Curves\n\nYou can customize the default easing curve at MovieTween, scene or property tween level.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/movie_tween/curve.dart --\u003e\n```dart\nfinal tween = MovieTween(curve: Curves.easeIn);\n\n// scene1 will use Curves.easeIn defined by the MovieTween\nfinal scene1 = tween.scene(duration: const Duration(seconds: 1));\n\n// scene2 will use Curves.easeOut\nfinal scene2 =\n    tween.scene(duration: const Duration(seconds: 1), curve: Curves.easeOut);\n\n// will use Curves.easeIn defined by the MovieTween\nscene1.tween('value1', Tween(begin: 0.0, end: 100.0));\n\n// will use Curves.easeOut defined by scene2\nscene2.tween('value2', Tween(begin: 0.0, end: 100.0));\n\n// will use Curves.easeInOut defined by property tween\nscene2.tween('value3', Tween(begin: 0.0, end: 100.0),\n    curve: Curves.easeInOut);\n```\n\u003c!-- // end of #code --\u003e\n\n### Extrapolation\n\nAll values that are not explicitly set in the timeline will be extrapolated.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/movie_tween/extrapolation.dart --\u003e\n```dart\nfinal tween = MovieTween()\n\n  // implicitly use 100.0 for width values from 0.0s - 1.0s\n\n  // 1.0s - 2.0s\n  ..scene(\n    begin: const Duration(seconds: 1),\n    duration: const Duration(seconds: 1),\n  ).tween('width', Tween\u003cdouble\u003e(begin: 100.0, end: 200.0))\n\n  // implicitly use 200.0 for width values from 2.0s - 3.0s\n\n  // 3.0s - 4.0s\n  ..scene(\n    begin: const Duration(seconds: 3),\n    end: const Duration(seconds: 4),\n  ).tween('height', Tween\u003cdouble\u003e(begin: 400.0, end: 500.0));\n```\n\u003c!-- // end of #code --\u003e\n\n### Use developer tools\n\nCreating complex tweens with multiple or staggered properties can be time consuming to create and maintain. I recommend using the [**Animation Developer Tools**](#animation-developer-tools) to streamline this process.\n\n![devtools](https://github.com/felixblaschke/simple_animations/raw/main/example/img/d1.gif)\n\n### Animation duration\n\nNormally an `Animatable` or `Tween` doesn't contain a duration information. But `MovieTween` class contains a `duration` property that contains the total duration of the animation.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/movie_tween/duration.dart --\u003e\n```dart\n@override\nWidget build(BuildContext context) {\n  final tween = MovieTween()\n    ..tween('width', Tween\u003cdouble\u003e(begin: 0.0, end: 100.0),\n        duration: const Duration(milliseconds: 700))\n    ..tween('height', Tween\u003cdouble\u003e(begin: 300.0, end: 200.0),\n        duration: const Duration(milliseconds: 700));\n\n  return PlayAnimationBuilder\u003cMovie\u003e(\n    tween: tween,\n    duration: tween.duration, // use duration from MovieTween\n    builder: (context, value, _) {\n      return Container(\n        width: value.get('width'),\n        height: value.get('height'),\n        color: Colors.yellow,\n      );\n    },\n  );\n}\n```\n\u003c!-- // end of #code --\u003e\n\n_Hint: You can also multiply the `duration` value with a numeric factor in order to speed up or slow down an animation._\n\nOf cause you can also use an own `Duration` for the animation.\n\n\u0026nbsp;\n\n## Animation Mixin\n\nIt reduces boilerplate code when using `AnimationController` instances.\n\n### Basic usage pattern\n\nCreate an `AnimationController` just by adding `AnimationMixin` to your stateful widget:\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/animation_mixin/basic.dart --\u003e\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:simple_animations/simple_animations.dart';\n\nclass MyAnimatedWidget extends StatefulWidget {\n  const MyAnimatedWidget({super.key});\n\n  @override\n  _MyAnimatedWidgetState createState() =\u003e _MyAnimatedWidgetState();\n}\n\n// Add AnimationMixin to state class\nclass _MyAnimatedWidgetState extends State\u003cMyAnimatedWidget\u003e\n    with AnimationMixin {\n  late Animation\u003cdouble\u003e size;\n\n  @override\n  void initState() {\n    size = Tween\u003cdouble\u003e(begin: 0.0, end: 200.0).animate(controller);\n    controller.play();\n    super.initState();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Container(width: size.value, height: size.value, color: Colors.red);\n  }\n}\n```\n\u003c!-- // end of #code --\u003e\n\n💪 The `AnimationMixin` generates a preconfigured AnimationController as `controller`. You can just use it. No need to worry about initialization or disposing.\n\n### Create multiple AnimationController\n\nWith multiple AnimationController you can have many parallel animations at the same time.\n\nAnicoto's `AnimationMixin` enhances your **state class** with a method `createController()` to create multiple **managed\\*** AnimationController. _(\"Managed\" means that you don't need to care about initialization and disposing.)_\n\n#### Create a managed AnimationController\n\nFirst create a class variable of type `AnimationController`. Then inside the `initState() {...}` method call `createController()`. That's all.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/animation_mixin/managed1.dart --\u003e\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:simple_animations/simple_animations.dart';\n\nclass MyAnimatedWidget extends StatefulWidget {\n  const MyAnimatedWidget({super.key});\n\n  @override\n  _MyAnimatedWidgetState createState() =\u003e _MyAnimatedWidgetState();\n}\n\n// use AnimationMixin\nclass _MyAnimatedWidgetState extends State\u003cMyAnimatedWidget\u003e\n    with AnimationMixin {\n  late AnimationController sizeController; // declare custom AnimationController\n  late Animation\u003cdouble\u003e size;\n\n  @override\n  void initState() {\n    sizeController = createController(); // create custom AnimationController\n    size = Tween\u003cdouble\u003e(begin: 0.0, end: 200.0).animate(sizeController);\n    sizeController.play(duration: const Duration(seconds: 5));\n    super.initState();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Container(width: size.value, height: size.value, color: Colors.red);\n  }\n}\n```\n\u003c!-- // end of #code --\u003e\n\n#### Create many managed AnimationController\n\nAnicoto allows you to have as many AnimationController you want. Behind the scenes it keeps track of them.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/animation_mixin/managed2.dart --\u003e\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:simple_animations/simple_animations.dart';\n\nclass MyAnimatedWidget extends StatefulWidget {\n  const MyAnimatedWidget({super.key});\n\n  @override\n  _MyAnimatedWidgetState createState() =\u003e _MyAnimatedWidgetState();\n}\n\nclass _MyAnimatedWidgetState extends State\u003cMyAnimatedWidget\u003e\n    with AnimationMixin {\n  late AnimationController widthController;\n  late AnimationController heightController;\n  late AnimationController colorController;\n\n  late Animation\u003cdouble\u003e width;\n  late Animation\u003cdouble\u003e height;\n  late Animation\u003cColor?\u003e color;\n\n  @override\n  void initState() {\n    widthController = createController()\n      ..mirror(duration: const Duration(seconds: 5));\n    heightController = createController()\n      ..mirror(duration: const Duration(seconds: 3));\n    colorController = createController()\n      ..mirror(duration: const Duration(milliseconds: 1500));\n\n    width = Tween\u003cdouble\u003e(begin: 100.0, end: 200.0).animate(widthController);\n    height = Tween\u003cdouble\u003e(begin: 100.0, end: 200.0).animate(heightController);\n    color = ColorTween(begin: Colors.red, end: Colors.blue)\n        .animate(colorController);\n\n    super.initState();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Container(\n        width: width.value, height: height.value, color: color.value);\n  }\n}\n```\n\u003c!-- // end of #code --\u003e\n\n\u0026nbsp;\n\n## Shortcuts for AnimationController\n\nThe extension for `AnimationController` adds four convenience functions:\n\n- `controller.play()` plays animation and stops at the end.\n\n- `controller.playReverse()` plays animation reversed and stops at the start.\n\n- `controller.loop()` repetitively plays the animation from start to the end.\n\n- `controller.mirror()` repetitively plays the animation forward, then backwards, then forward and so on.\n\nEach of these methods take an optional `duration` named parameter to configure your animation action within one line of code.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/animation_controller_extension/shortcuts.dart --\u003e\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:simple_animations/simple_animations.dart';\n\nvoid someFunction(AnimationController controller) {\n  controller.play(duration: const Duration(milliseconds: 1500));\n  controller.playReverse(duration: const Duration(milliseconds: 1500));\n  controller.loop(duration: const Duration(milliseconds: 1500));\n  controller.mirror(duration: const Duration(milliseconds: 1500));\n}\n```\n\u003c!-- // end of #code --\u003e\n\nYou can use these methods nicely along the already existing `controller.stop()` and `controller.reset()` methods.\n\n\u0026nbsp;\n\n## Animation Developer Tools\n\nThe Animation Developer Tools allow you to create or review your animation step by step.\n\n### Basic usage pattern\n\nWrap your UI with the `AnimationDeveloperTools` widget.\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/animation_developer_tools/intro.dart --\u003e\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:simple_animations/simple_animations.dart';\n\nclass MyPage extends StatelessWidget {\n  const MyPage({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      // put DevTools very high in the widget hierarchy\n      body: AnimationDeveloperTools(\n        child: Container(), // your UI\n      ),\n    );\n  }\n}\n```\n\u003c!-- // end of #code --\u003e\n\nEnable developer mode on the animation you want to debug.\n\n#### Using Animation Builder widgets\n\nThe Animation Builder widgets\n\n- `PlayAnimationBuilder`\n- `LoopAnimationBuilder`\n- `MirrorAnimationBuilder`\n- `CustomAnimationBuilder`\n\nhave a constructor parameter `developerMode` that can be set to `true`. It will connect to the closest `AnimationDeveloperTools` widget.\n\n**Example**\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/animation_developer_tools/animation_builder.dart --\u003e\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:simple_animations/simple_animations.dart';\n\nvoid main() =\u003e runApp(const MaterialApp(home: Scaffold(body: MyPage())));\n\nclass MyPage extends StatelessWidget {\n  const MyPage({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return SafeArea(\n      // put DevTools very high in the widget hierarchy\n      child: AnimationDeveloperTools(\n        child: Center(\n          child: PlayAnimationBuilder\u003cdouble\u003e(\n            tween: Tween\u003cdouble\u003e(begin: 0.0, end: 100.0),\n            duration: const Duration(seconds: 1),\n            developerMode: true, // enable developer mode\n            builder: (context, value, child) {\n              return Container(\n                width: value,\n                height: value,\n                color: Colors.blue,\n              );\n            },\n          ),\n        ),\n      ),\n    );\n  }\n}\n```\n\u003c!-- // end of #code --\u003e\n\n![devtools](https://github.com/felixblaschke/simple_animations/raw/main/example/img/d1.gif)\n\n#### Using Animation Mixin\n\nIf your stateful widget uses `AnimationMixin` to manage your instances of `AnimationController` you can call `enableDeveloperMode()` to connect to the clostest `AnimationDeveloperMode` widget.\n\n**Example**\n\n\u003c!-- #code example/sa_flutter_app/lib/readme/animation_developer_tools/animation_mixin.dart --\u003e\n```dart\nimport 'package:flutter/material.dart';\nimport 'package:simple_animations/simple_animations.dart';\n\nvoid main() =\u003e runApp(const MyApp());\n\nclass MyApp extends StatelessWidget {\n  const MyApp({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return const MaterialApp(\n      home: Scaffold(\n        body: SafeArea(\n          // put DevTools very high in the widget hierarchy\n          child: AnimationDeveloperTools(\n            child: Center(\n              child: MyAnimation(),\n            ),\n          ),\n        ),\n      ),\n    );\n  }\n}\n\nclass MyAnimation extends StatefulWidget {\n  const MyAnimation({super.key});\n\n  @override\n  _MyAnimationState createState() =\u003e _MyAnimationState();\n}\n\nclass _MyAnimationState extends State\u003cMyAnimation\u003e with AnimationMixin {\n  late Animation\u003cdouble\u003e size;\n\n  @override\n  void initState() {\n    size = Tween\u003cdouble\u003e(begin: 0.0, end: 100.0).animate(controller);\n    enableDeveloperMode(controller); // enable developer mode\n    controller.forward();\n    super.initState();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Container(width: size.value, height: size.value, color: Colors.blue);\n  }\n}\n```\n\u003c!-- // end of #code --\u003e\n\n### Features and tricks\n\nThe Animation Developer Tools come with several features that simplify your developer life:\n\n- Regardless of the real animation, with developer mode activated the animation will always loop.\n- You can use Flutter hot reloading for editing and debugging if your tween is created stateless.\n- Use the slider to edit the animated scene while pausing.\n- You can slow down the animation to look out for certain details.\n- Use the interval buttons to focus on a time span of the animation.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffelixblaschke%2Fsimple_animations","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffelixblaschke%2Fsimple_animations","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffelixblaschke%2Fsimple_animations/lists"}