Amazing Animated Backgrounds For Flutter App

In this post, I have collected the background animations in the flutter app, How to use beautiful and attractive animations to enhance the beauty of the flutter app.

Particle Backgrounds, Rainy Background , Bubbles Background, And Snow Background.

1. Flutter Particles ( flutter_particles )

A Flutter widget for creating particle Background.

Demo


Intallation 

Add the dependencies needed to your pubspec.yaml file.

Usage 

Import the file

import 'package:flutter_particles/particles.dart';

Calling the widget

Demo

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      backgroundColor: Colors.orange[50],
      body: new Particles(
        30, // Number of Particles
        Colors.blue, // Color of Particles
      ),
    );
  }
}
Demo



2. Fancy background animations in Flutter

The animation consists of a background gradient with a smooth transition. Below there are multiple waves sliding from right to left. On top, there is some content.

Image for post

Let’s start with the background gradient. We use Flutter’s build-in BoxDecoration to apply a LinearGradient like this:
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [color1, color2])),
);
 

We need to animate it. For This, We use a simple_animations Flutter package. We use MultiTrackTween (an Animatable to arrange the tweening of multiple properties at once) in combination with ControlledAnimation (a widget to very simple run tween-based animations without overhead).

import class AnimatedBackground extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final tween = MultiTrackTween([
      Track("color1").add(Duration(seconds: 3),
          ColorTween(begin: Color(0xffD38312), end: Colors.lightBlue.shade900)),
      Track("color2").add(Duration(seconds: 3),
          ColorTween(begin: Color(0xffA83279), end: Colors.blue.shade600))
    ]);

    return ControlledAnimation(
      playback: Playback.MIRROR,
      tween: tween,
      duration: tween.duration,
      builder: (context, animation) {
        return Container(
          decoration: BoxDecoration(
              gradient: LinearGradient(
                  begin: Alignment.topCenter,
                  end: Alignment.bottomCenter,
                  colors: [animation["color1"], animation["color2"]])),
        );
      },
    );
  }
};

Now that we have solved the math, we can put it inside a widget:


import class AnimatedWave extends StatelessWidget {
  final double height;
  final double speed;
  final double offset;

  AnimatedWave({this.height, this.speed, this.offset = 0.0});

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(builder: (context, constraints) {
      return Container(
        height: height,
        width: constraints.biggest.width,
        child: ControlledAnimation(
            playback: Playback.LOOP,
            duration: Duration(milliseconds: (5000 / speed).round()),
            tween: Tween(begin: 0.0, end: 2 * pi),
            builder: (context, value) {
              return CustomPaint(
                foregroundPainter: CurvePainter(value + offset),
              );
            }),
      );
    });
  }
}

class CurvePainter extends CustomPainter {
  final double value;

  CurvePainter(this.value);

  @override
  void paint(Canvas canvas, Size size) {
    final white = Paint()..color = Colors.white.withAlpha(60);
    final path = Path();

    final y1 = sin(value);
    final y2 = sin(value + pi / 2);
    final y3 = sin(value + pi);

    final startPointY = size.height * (0.5 + 0.4 * y1);
    final controlPointY = size.height * (0.5 + 0.4 * y2);
    final endPointY = size.height * (0.5 + 0.4 * y3);

    path.moveTo(size.width * 0, startPointY);
    path.quadraticBezierTo(
        size.width * 0.5, controlPointY, size.width, endPointY);
    path.lineTo(size.width, size.height);
    path.lineTo(0, size.height);
    path.close();
    canvas.drawPath(path, white);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
};

For the widget part, we need a LayoutBuilder to retrieve the available width to paint on. Then we utilize a ControlledAnimation (from flutter_animation) with Playback.LOOP and a simple tween from 0.0 to 2*pi. We animate a Canvas that passes the current animation value to a CustomPainter.

Finally, we put everything together. I am using a Stack widget and first put in the gradient background, followed by multiple wave animations. Last the content of the app: a text in my example.




import class FancyBackgroundApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Positioned.fill(child: AnimatedBackground()),
        onBottom(AnimatedWave(
          height: 180,
          speed: 1.0,
        )),
        onBottom(AnimatedWave(
          height: 120,
          speed: 0.9,
          offset: pi,
        )),
        onBottom(AnimatedWave(
          height: 220,
          speed: 1.2,
          offset: pi / 2,
        )),
        Positioned.fill(child: CenteredText()),
      ],
    );
  }

  onBottom(Widget child) => Positioned.fill(
        child: Align(
          alignment: Alignment.bottomCenter,
          child: child,
        ),
      );
};



3. Animated Backgrounds for Flutter( animated_background )

Animated Backgrounds for Flutter. Easily extended to paint whatever you want on the canvas.

Screenshot




Note: These examples are laggy because they were recorded from the emulator. Other examples available in the screenshots folder.

How to use 

In your pubspec.yaml:

dependencies:
  animated_background: ^1.0.5

In your Dart file:

import 'package:animated_background/animated_background.dart';

Use in a Stateful Widget with mixin TickerProviderStateMixin or pass a ticker provider in vsync.

AnimatedBackground(
  behaviour: RandomParticleBehaviour(),
  vsync: this,
  child: Text('Hello'),
);

Screenshot



4. SpriteWidget ( spritewidget )


SpriteWidget is a toolkit for building complex, high performance animations and 2D games with Flutter. Your sprite render tree lives inside a widget that mixes seamlessly with other Flutter and Material widgets. You can use SpriteWidget to create anything from an animated icon to a full fledged game.

This guide assumes a basic knowledge of Flutter and Dart. Get support by posting a question tagged spritewidget on StackOverflow.

You can find examples in the examples directory, or check out the complete Space Blast game.

enter image description here


code snippet for rain


import // Rain layer. Uses three layers of particle systems, to create a parallax
// rain effect.
class Rain extends Node {
  Rain() {
    _addParticles(1.0);
    _addParticles(1.5);
    _addParticles(2.0);
  }

  List _particles = [];

  void _addParticles(double distance) {
    ParticleSystem particles = new ParticleSystem(
      _sprites['raindrop.png'],
      transferMode: BlendMode.srcATop,
      posVar: const Offset(1300.0, 0.0),
      direction: 90.0,
      directionVar: 0.0,
      speed: 1000.0 / distance,
      speedVar: 100.0 / distance,
      startSize: 1.2 / distance,
      startSizeVar: 0.2 / distance,
      endSize: 1.2 / distance,
      endSizeVar: 0.2 / distance,
      life: 1.5 * distance,
      lifeVar: 1.0 * distance
    );
    particles.position = const Offset(1024.0, -200.0);
    particles.rotation = 10.0;
    particles.opacity = 0.0;

    _particles.add(particles);
    addChild(particles);
  };



5. snow_effect 

Simple Snow Effect in Flutter

Setting CustomTool


import import 'dart:math';

import 'package:flutter/material.dart';

class SnowWidget extends StatefulWidget {
  final int totalSnow;
  final double speed;
  final bool isRunning;

  SnowWidget({Key key, this.totalSnow, this.speed, this.isRunning})
      : super(key: key);

  _SnowWidgetState createState() => _SnowWidgetState();
}

class _SnowWidgetState extends State
    with SingleTickerProviderStateMixin {
  Random _rnd;
  AnimationController controller;
  Animation animation;
  List _snows;
  double angle = 0;
  double W = 0;
  double H = 0;
  @override
  void initState() {
    super.initState();
    init();
  }

  init() {
    _rnd = new Random();
    if (controller == null) {
      controller = new AnimationController(
          lowerBound: 0,
          upperBound: 1,
          vsync: this,
          duration: const Duration(milliseconds: 20000));
      controller.addListener(() {
        if (mounted) {
          setState(() {
            update();
          });
        }
      });
    }
    if (!widget.isRunning) {
      controller.stop();
    } else {
      controller.repeat();
    }
  }

  @override
  dispose() {
    controller.dispose();
    super.dispose();
  }

  _createSnow() {
    _snows = new List();
    for (var i = 0; i < widget.totalSnow; i++) {
      _snows.add(new Snow(
          x: _rnd.nextDouble() * W,
          y: _rnd.nextDouble() * H,
          r: _rnd.nextDouble() * 4 + 1,
          d: _rnd.nextDouble() * widget.speed));
    }
  }

  update() {
    print(" update" + widget.isRunning.toString());
    angle += 0.01;
    if (_snows == null || widget.totalSnow != _snows.length) {
      _createSnow();
    }
    for (var i = 0; i < widget.totalSnow; i++) {
      var snow = _snows[i];
      //We will add 1 to the cos function to prevent negative values which will lead flakes to move upwards
      //Every particle has its own density which can be used to make the downward movement different for each flake
      //Lets make it more random by adding in the radius
      snow.y += (cos(angle + snow.d) + 1 + snow.r / 2) * widget.speed;
      snow.x += sin(angle) * 2 * widget.speed;
      if (snow.x > W + 5 || snow.x < -5 || snow.y > H) {
        if (i % 3 > 0) {
          //66.67% of the flakes
          _snows[i] =
              new Snow(x: _rnd.nextDouble() * W, y: -10, r: snow.r, d: snow.d);
        } else {
          //If the flake is exitting from the right
          if (sin(angle) > 0) {
            //Enter from the left
            _snows[i] =
                new Snow(x: -5, y: _rnd.nextDouble() * H, r: snow.r, d: snow.d);
          } else {
            //Enter from the right
            _snows[i] = new Snow(
                x: W + 5, y: _rnd.nextDouble() * H, r: snow.r, d: snow.d);
          }
        }
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    if (widget.isRunning && !controller.isAnimating) {
      controller.repeat();
    } else if (!widget.isRunning && controller.isAnimating) {
      controller.stop();
    }

    return LayoutBuilder(
      builder: (context, constraints) {
        if (_snows == null) {
          W = constraints.maxWidth;
          H = constraints.maxHeight;
        }
        return CustomPaint(
          willChange: widget.isRunning,
          painter: SnowPainter(
              // progress: controller.value,
              isRunning: widget.isRunning,
              snows: _snows),
          size: Size.infinite,
        );
      },
    );
  }
}

class Snow {
  double x;
  double y;
  double r; //radius
  double d; //density
  Snow({this.x, this.y, this.r, this.d});
}

class SnowPainter extends CustomPainter {
  List snows;
  bool isRunning;

  SnowPainter({this.isRunning, this.snows});

  @override
  void paint(Canvas canvas, Size size) {
    if (snows == null || !isRunning) return;
    //draw circle
    final Paint paint = new Paint()
      ..color = Colors.white
      ..strokeCap = StrokeCap.round
      ..strokeWidth = 10.0;
    for (var i = 0; i < snows.length; i++) {
      var snow = snows[i];
      if (snow != null) {
        canvas.drawCircle(Offset(snow.x, snow.y), snow.r, paint);
      }
    }
  }

  @override
  bool shouldRepaint(SnowPainter oldDelegate) => isRunning;
};

It is the main.dart file used with the above code.


import import 'package:flutter/material.dart';
import 'package:snow_effect/snow-animation.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State
    with SingleTickerProviderStateMixin {
  bool _isRunning = true;

  @override
  void initState() {
    super.initState();
  }

  //anim
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          Container(
              color: Colors.blue,
              width: MediaQuery.of(context).size.width,
              height: MediaQuery.of(context).size.height),
          Container(
            child: SnowWidget(
              isRunning: _isRunning,
              totalSnow: 150,
              speed: 1,
            ),
          ),
          Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text(
                  'Status :' + _isRunning.toString(),
                  style: TextStyle(color: Colors.white),
                ),
              ],
            ),
          )
        ],
      ),
      floatingActionButton: new FloatingActionButton(
        child: new Icon(Icons.clear),
        onPressed: () {
          _isRunning = !_isRunning;
          setState(() {});
        },
      ),
      // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
};


6. Bubbles Animations in Flutter



Show you a way of creating a beautiful particle bubbles animation with Flutter. It’s based on the latest features of the Simple Animations package.

The animation consists of a color-fading background, a lot of bubbles floating up from the bottom to the top, and some content text.

Image for post


The particle model
Here is the dart code of our particle model:


import class ParticleModel {
  Animatable tween;
  double size;
  AnimationProgress animationProgress;
  Random random;

  ParticleModel(this.random) {
    restart();
  }

  restart({Duration time = Duration.zero}) {
    final startPosition = Offset(-0.2 + 1.4 * random.nextDouble(), 1.2);
    final endPosition = Offset(-0.2 + 1.4 * random.nextDouble(), -0.2);
    final duration = Duration(milliseconds: 500 + random.nextInt(1000));

    tween = MultiTrackTween([
      Track("x").add(
          duration, Tween(begin: startPosition.dx, end: endPosition.dx),
          curve: Curves.easeInOutSine),
      Track("y").add(
          duration, Tween(begin: startPosition.dy, end: endPosition.dy),
          curve: Curves.easeIn),
    ]);
    animationProgress = AnimationProgress(duration: duration, startTime: time);
    size = 0.2 + random.nextDouble() * 0.4;
  }

  maintainRestart(Duration time) {
    if (animationProgress.progress(time) == 1.0) {
      restart(time: time);
    }
  }
};

Drawing the particles
Since we have the model including the life cycle of our particle system, it’s time to draw them. For this propose we create a CustomPainter that draws a list of particles:



import class ParticlePainter extends CustomPainter {
  List particles;
  Duration time;

  ParticlePainter(this.particles, this.time);

  @override
  void paint(Canvas canvas, Size size) {
    final paint = Paint()..color = Colors.white.withAlpha(50);

    particles.forEach((particle) {
      var progress = particle.animationProgress.progress(time);
      final animation = particle.tween.transform(progress);
      final position =
          Offset(animation["x"] * size.width, animation["y"] * size.height);
      canvas.drawCircle(position, size.width * 0.2 * particle.size, paint);
    });
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => true;
};

It’s widget time

Until here we modeled the particle system and know how to draw them. Let us now create a widget that will render them:


import class Particles extends StatefulWidget {
  final int numberOfParticles;

  Particles(this.numberOfParticles);

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

class _ParticlesState extends State {
  final Random random = Random();

  final List particles = [];

  @override
  void initState() {
    List.generate(widget.numberOfParticles, (index) {
      particles.add(ParticleModel(random));
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Rendering(
      builder: (context, time) {
        _simulateParticles(time);
        return CustomPaint(
          painter: ParticlePainter(particles, time),
        );
      },
    );
  }

  _simulateParticles(Duration time) {
    particles.forEach((particle) => particle.maintainRestart(time));
  }
};





import @override
Widget build(BuildContext context) {
  return Rendering(
    startTime: Duration(seconds: 30),
    onTick: _simulateParticles,
    builder: (context, time) {
      return CustomPaint(
        painter: ParticlePainter(particles, time),
      );
    },
  );
}



class ParticleBackgroundApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Stack(children: [
      Positioned.fill(child: AnimatedBackground()),
      Positioned.fill(child: Particles(30)),
      Positioned.fill(child: CenteredText()),
    ]);
  }
};


It was all about flutter background animations...
If you like it please comment on us by sharing your Good thoughts.
Thank You.













Post a Comment

0 Comments