Particle Animations with Flutter

This article covers a previous version of Simple Animation. The basics stay the same but class names have changed.

Today I want to show you a way of creating a beautiful particle animation with Flutter. It’s based on the latest features of the Simple Animations package.

Watch high resolution video on YouTube.

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

The bubbles

The most interesting part of this animation are the bubbles. I am using about 30 of them in a particle system. When creating a bubble it chooses a random start position at the bottom and a random target position at the top. It also have a random size along with a random speed.

If a bubble reaches the top it will be re-created with random properties again. This will look like this:

Life cycle of one particle.

The particle model

Here is the dart code of our particle model:

We pass in a random generator and immediately restarting the particle. In the restart function we define start position and end position in relative screen space. (For the y-values it means 0.0 is top, 1.0 is bottom and 1.2 is 20% below the bottom. For x-values its similar.)

We use these positions to create a tween. I am using MultiTrackTween that tweens multiple properties at once. I want my x-position and y-position to be animated differently and can apply some nice easing effect.

Then we create an AnimationProgress that will supply our tween with the actual progress of our tweened animation. It takes a start time and a duration. To get the proper start time we expect someone passing the current time into our restart function.

For duration and size we can just choose some random values. Nothing special about them.

Last but not least we have a maintainRestart function that is called from outside to check if a particle needs to be restarted. It queries the AnimationProgress by calling it’s progress(time) function. It will return the progress of the animation (a value between 0.0 and 1.0) based on the current time, the specified start time and duration.

MultiTrackTween and AnimationProgress are both parts of the Simple Animation package.

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:

We pass in our particles and the current time. In the paint function we iterate over all particles and query their progress value (supplied by AnimationProgress).

Then we pass this progress value into our specified tween to get the actual relative positions of our animations.

Finally we multiply them with the size of the canvas to get absolute positions that we can draw.

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:

We create a stateful widget that creates some particle models on initialization.

The build function uses the Rendering widget (coming from Simple Animation package) that supplies our painter and life cycle with a time. It continuously builds a widget for each frame.

The time is a Duration that starts at zero and then counts up in real time. We can use this time to create frame-rate independent animations. That’s also the reason why AnimationProgress is based on time.

The result will look like this:

It looks fine but we have one issue. Since all 30 particles restart at the beginning there are no bubbles at the upper part of the screen.

Time traveling

To fix this issue we tell our Rendering widget to compute a different start time.

We can add a parameter startTime that will cause the Rendering widget to fast-forward compute the animation. For that we need to put all life cycle related code into the onTick function. (You can find more details in the documentation of the Rendering widget)

When we are now starting the animation, all bubbles are well distributed around the screen from the beginning:

Putting it all together

For the background fading we used an animated linear gradient that I already covered in my previous article Fancy Background animation.

All parts are put on a Stack widget:

And this is the final result:

Watch high resolution video on YouTube.

You can view the whole code here as a part of the Simple Animation Example App. You can live view this demo on your device by downloading it from the Play Store.

You find the Simple Animation package on pub dart.

If you like my work leave some claps.

Happy bubble party,
— Felix —

Software Developer,