Original link: medium.com/felixblasc…
This article mainly introduces how to usesimple_animationsAchieve beautiful animation effect. The Demo:gsy_flutter_demo
This article will introduce some interesting animations that can make Flutter pages look friendlier, and also show how to easily animate Flutter using the Simple_animations library, as shown below.
What the animation needs to show is a smooth gradient background with multiple waves sliding from right to left underneath the text.
The built-in BoxDecoration of the Flutter supports the LinearGradient effect to achieve the gradient effect as follows:
return Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [color1, color2])),
);
Copy the code
So we just need to set up animations on this basis. Here we use simple_animations directly to achieve the effect. In simple_animations we can use these two objects to achieve the effect:
MultiTrackTween
(Animate objects that arrange the properties of multiple tween animations at once)ControlledAnimation
(A very simple tween animation based control object)
The implementation of the waveform will be introduced in a later article. Here is the code for background gradient:
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"]]))); }); }}Copy the code
As shown in the code above, here we just define the colors color1 and color2 of the two tracks and set them to the ControlledAnimation. Finally, we use these two colors in the LinearGradient.
If it seems simple enough, and you don’t even see any StatefulWidgets or AnimationControllers, you can use this code as a template and extend it with more complex color transitions.
Now that we have an animation with a gradient background, we can add some new animation effects to improve the effect. Here is what we want to achieve:
In fact, this is the effect of three wave patterns overlapping each other, and we need to make sure that they are independent of each other so that we can eventually create a ripple effect.
So we need to define a widget with the following properties for WaveAnimation:
speed
: Controls the duration of wave animation;height
: set the area of wave action;offset
: x axis offset to give different waveform “starting position”;
Next we first want to discuss a mathematical problem, how to achieve a cyclical circular arc animation effect? There is only one answer: trigonometry.
First we need to set a value between 0.0 and 2 * PI for the animation and put that value into the sine function. Then we sample the value of y at three locations: left, middle, and end. This covers an interval of the size of PI from left to right, so we can always see half of a complete sine wave.
Why do we sample three locations? Because we draw a Path based on these three positions, the following image provides this visualization:
We start at the top left corner (purple) and add a quadratic Bezier function to the top right (red). We can then make this change by specifying a “control point” (green). Finally, we draw a Path using the Canvas Path of the Flutter.
And then we move the red one to the orange one, and then we move the purple one to the yellow one, and finally we just have to connect the Path to the Path.
When you focus only on the purple, green, and red dots, you can see that our sampled path is a sine wave effect.
This quadratic Bezier function may seem weird at first, but it just wants to draw a straight line from purple to red (blue). The longer the distance between it and the green dot, the gray shape of the line is affected by something like gravity, and the end result is that the line gradually bends.
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) {
returnContainer( 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) {returnCustomPaint( 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 (sie.width * 0.5, controlPointY, sie.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; }}Copy the code
For this control, we used a LayoutBuilder to check the available widths and draw, then ControlledAnimation and Playable. LOOP to implement simple tween data from 0.0 to 2 * PI. You can then pass the current animation value to the CustomPainter Canvas for animation.
In the end this CustomPainter can achieve the waveform path we want, but it is important to note that the waveforms and opacity we use need to be reduced layer by layer so that multiple waves overlap and are always visible.
Did you implement cool animations with relatively little code?
Finally, as shown in the code below, we use Stack to Stack the controls together.
class FancyBackgroundApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
returnStack( children: <Widget>[ 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: PI,)), onBottom(AnimatedWave(height: 220, speed: PI,)) 21, jam. 1.2, offset: PI / 2,)), would offer tourists a small glimpse of space. } onBottom(Widget child) => Positioned.fill( child: Align( alignment: Alignment.bottomCenter, child: child, ), ); }Copy the code
Flutter article summary address:
A complete series of articles on Flutter
A series of articles on the world outside Flutter
Resources to recommend
- Dart: gSY_flutter_demo /anim_bg_demo_page.dart
- Making: github.com/CarGuo
- Open Source Flutter complete project:Github.com/CarGuo/GSYG…
- Open Source Flutter Multi-case learning project:Github.com/CarGuo/GSYF…
- Open Source Fluttre Combat Ebook Project:Github.com/CarGuo/GSYF…
- Open Source React Native project: github.com/CarGuo/GSYG…