You feel that this system is ready for the next step: animations.

Previously, you have used AnimationController to animate things with Flutter and don’t want this case to be an exception. So what you want to do is somehow start redrawing the CustomPainter when AnimationController frame is ready.

You put your 🤔 face on, but only for as long as it took you to think “There should be a widget for that”.

Sure enough, just less than a minute later, here it is, right in a new tab of your browser: AnimatedBuilder. The core essence of that one is that it takes an AnimationController (just what you want, nice), and rebuilds as soon as it’s being animated.

Great power comes out of greater simplicity creating immense extendability, as it often happens in software.

Your next move is to add a new sibling to Drawable . Without any overthinking (just around 5 minutes spent on naming), you call it Updatable . You just want it to take your AnimationController and… do its magic, whatever.

You’re opting into implementing fading as first animated behavior, cause it’s simple, and opacity could behave exactly like AnimationController value , just change from 0 to 1 .

So, Fading would behave as following, when update is called, it would simply set its opacity to the value of AnimationController . Simple and sweet, you definitely kissed it.

And now, you’re linking it with Drawable behaviour, by creating a new class to utilize this mixin: FadingRect . You want that one to draw a Rect with opacity from Fading .

Just as you hit Enter one last line to finish typing this code, your sight stops for a fraction of second on a tab where you searched for “Gut feeling”. And you think that this FadingRect has a lot of guts to hide from outlying users of it. Your next thought is simple and clear, “Hide the guts”. You decide that’s it’s a good time to actually name all these components combined after what they are. So you create your first blueprint of a Particle .

Despite the class being abstract , you leave implementations of Drawable and Updatable explicitly empty. You find it useful that classes extending Particle won’t have to explicitly implement them all the time.

With that, you rewrite the FadingRect to be based on a Particle .

You can’t stop yourself from reading the declaration. Fading rect extends particle with fading. It looks like a definition on its own and you like when it’s possible to write code that expressive.

That code almost distracted you from the fact that DrawablePainter doesn’t know what Particle is and can’t work with AnimationController . “World needs a new hero,” booms in your head.

World meets new hero without enthusiasm you’d expect. In fact, you’re the only one to witness its birth, and will probably remain an only person knowing of its existence. What a lonely hero you’ve just created.

To make its life a bit less miserable, you think it could use a friend. A Flutter-friend. A parent widget, to be more precise. You don’t want to mess with creating new SingleTickerProviderStateMixin or limit yourself to use only StatefulWidget for your particles, so you decide to create a wrapper which would make creating Puffs and Zaps a bit easier.

So, as you usually do, first of all, you write the code showing how would you like to use it. Or, as smart guys call, API-driven design.

So, you just want to have a widget which would take another widget as a child, and a particle which would be drawn somehow. That’s a good start, but then you realise that calling code would most likely want to control when particles are appearing.

That is same as calling child widget methods from a parent widget. In Flutter it could be solved by either using Key to obtain a reference to children state, or by using builder property pattern. You choose the latter as it assumes fewer restrictions on the client code part. So, instead of passing child to Particles , you pass builder .

For client code to know what to expect, you define a signature for your builder using the awesome typedef feature.

It would allow client code to make awful things to an AnimationController , to make it spill value in all directions and speeds.

With that in mind, the simplest example evolves slightly more complex simplest example.

So, now widget from within the builder could call controller.forward() whenever it’s a good time to start animating the Particles .

You want to illustrate that behavior a bit more details to yourself, so rewrite it with actually using the controller .

Having such an example, now it’s the easiest part left, to actually implement the Particles to behave in a way you just described.

You start with a scaffold of the basic scaffold from AnimatedBuilder docs and simply swap its builder to return the ParticlePainter instead. And then use the builder on Particles for obtaining a child for AnimatedBuilder .

And then modify OutlineButton.build slightly to use this new interface for Particles .

The effect is absolutely useless at this stage, but you’re almost done with the foundation and can’t wait to start Zapping and Puffing

After adding it to OutlineButton instead of DrawablePainter , it looks pretty boring, you have to admin. But it’s in your full power to make it cooler. The next thing you want to achieve is to make whole thing a bit more explosive 💥, by scaling the rectangle out, as well as to make it fade out instead of fading in.

First things first, you add a new mixin, for scaling, called Scaling using handy lerpDouble from dart:ui .

Next step is to have a Particle container for this behavior, which would apply the scaling to Canvas and pass control down the chain. Since it’s now quite clear that Particles are going to have a lot of… erm… children , you decide to express that behavior explicitly as well.

You’re quite sure this thing will allow you to move your Particle factory to the next level.

One other thing you could think of as a “particle factory”.

One neat trick you’re going to use is that in Dart when composing an entity from multiple mixins, it’s still possible to utilise inherited behaviour via using super . The key to that is to be aware that mixins are sequential. So, if someone would ask you to illustrate it, you would show something like the following code.

So, with your current setup, if you have more than one mixin competing for base update and draw methods to implement their behavior, it’s just important to not forget to call super , just like you did in NestedParticle .

With that, implementing a ScalingParticle is a breeze.

You like to think of this pattern as of cascade of control. The rule is just right-to-left, starting with whatever is written in original class method.

Cascade of control is just like the Telephone game, except you could trust the end result

So, during draw phase, ScalingParticle will rescale a new canvas layer and then pass control to NestedParticle which will ensure that child draw is called.

During update phase, as ScalingParticle doesn’t implement any behavior for it, Scaling update will be called, which will set current to an expected scale as per AnimationController value.

You feel great that you don’t have to learn all of this from complete scratch, but if you would, you would refer to this beautiful article.

You, next time explaining the mixin based inheritance in Dart to someone (after everyone will start using Flutter for everything).

Next part is fading out instead of fading in. Luckily, it’s really easy in your layered system. So you just go to Fading and add a new enum, FadingDirection to represent possible variations of fading behavior, as well as change how update behaves, depending on the value of that enum.

Nothing stops you from utilizing the new behaviors now.

But that looks a bit… meh, so you change the Particles duration to be const Duration(milliseconds: 300) . And parameterize the dimensions of FadingRect by adding a Size size field on that particle.

Now, it’s possible to set size of FadingRect to be something like FadingRect(size: Size(200, 200)) . And the picture becomes a little bit more enjoyable, resembling a splash after you’re tapping the buttons.

You wish 60 FPS GIFs wouldn’t weight as much as node_modules.

A little bit less boring again. You feel that quite soon you’ll move to actually interesting stuff. To make yourself one step closer to “Puff”, you think that you need some way to implement a “burst” of Particle instances in all directions.

You decide that it’s time for a CompositeParticle .

The composition is a good neighbour of layers when it comes to building such systems as per your experience. It happens very often that if you need to operate on a single entity of certain type, you may want to operate over multiple entities too. Another important thing is the symmetry.