preface

Not long ago, I used the weekend to learn and complete a simple Flutter project — Simple Weather, simple but not simple, rich but not complex. This simple Flutter weather project provides real-time, multi-day, 24-hour, typhoon path, voice broadcast and life index services. Supports location, deletion, and search.

The following picture shows the homepage effect. Click Download to experience it:

The project uses a large number of custom drawing widgets, rich custom chart effect on the home page and cool weather background animation. The dynamic effects of weather background show different effects under different weather conditions. At present, a total of 14 categories have been realized, including sunny, sunny and late, cloudy, overcast, small heavy rain, small heavy snow, fog, haze, floating dust and thunderstorm. Background dynamic effects are divided into three layers:

  • Background color layer. Gradient effect from top to bottom
  • The clouds. There is only one kind of picture, and different changes are made to its displacement, quantity and dyeing to achieve different effects
  • Information layer. Includes rain, snow, thunderstorm, and sun-up meteor effects

The implementation details of rain and snow were introduced in the article “Flutter- Drawing” to achieve cool rain and snow effects. Today, we will talk about how to achieve the dream meteor effect. Actually, it is not difficult to achieve, mainly the ideas and methods of implementation.

Without further words, let’s take a look at the dynamic renderings (in order to better preview the various background dynamic effects, in the upper right corner of the page about the entrance, you can change the weather type in real time, view the dynamic effects, interested download experience) :

Accompany you to see the meteor shower fall on this earth, let your tears fall on my shoulder, on my shoulder ~

Careful observation is not difficult to find that there are two main components:

  • Constantly flashing star effect
  • Fleeting meteor effect

Therefore, the following two parts will be explained in detail.

Clear night

Flutter has a lot in common with Android drawing. It provides canvas and Paint classes for drawing basic graphics, text and images. There are also many apis for adding cool effects such as gradient and Gaussian blur to simple graphics.

Initialize materials and parameters

Sunny and evening is composed of stars. First draw a star, which is easy to achieve without using pictures and directly draw on canvas. Flutter provides maskfilter.blur (_style, _sigma) and a blur(_paint. MaskFilter) to create a star glow effect.

BlurStyleThere are four categories: Normal, solid, outer, and outter, which correspond to the following effects:

_sigmaThe larger the fuzzy coefficient is, the more fuzzy it will be. Set 0, 1, 3 and 7 respectively under Normal.

Once you have the stars, you need to create them and give them properties to display on the screen.

class _StarParam {
  double x;
  double y;
  double alpha = 0.0;
  double scale;

  _StarParam();

  void init() {
    alpha = Random().nextDouble();
    scale = Random().nextDouble() * 0.1 + 0.6;
    x = Random().nextDouble() * 1.wp / scale;
    y = Random().nextDouble() * 0.3.hp / scale; }}Copy the code

In addition to the x and Y attributes, alpha is used for later animation, and scale is used to simulate near and far effects. We create 100 randomly distributed in 1*width and 0.3*height areas.

draw

Once you have arguments, you can draw directly by calling Canvas.drawcircle () :

  void drawStar(_StarParam param, Canvas canvas) {
    if (param == null) {
      return;
    }
    canvas.save();
    var identity = ColorFilter.matrix(<double> [1.0.0.0.0.0.1.0.0.0.0.0.1.0.0.0.0.0, param.alpha, 0,]); _paint.colorFilter = identity; canvas.scale(param.scale); canvas.drawCircle(Offset(param.x, param.y),3, _paint);
    canvas.restore();
  }
Copy the code

The implementation effect is as follows:

animation

The next step is to get the stars to move. Similar to the logic used to implement rain and snow, create a continuously running animation, constantly setState() in the animation callback, and for the star object, continuously incrementing or decrement the alpha field to achieve the flicker effect.

  void move() {
    if (reverse == true) {
      alpha -= 0.01;
      if (alpha < 0) { reset(); }}else {
      alpha += 0.01;
      if (alpha > 1.2) {
        reverse = true; }}}Copy the code

Here, when the alpha value reaches the threshold, the reverse field is set to true, and then the reverse field starts to decrement and disappear because many of the properties are random, resulting in the effect of the twinkling stars.

A shooting star

Initialize materials and parameters

At the beginning of preparation from a variety of picture material online to try to find a meteor resources, the result is not satisfactory, or is to all kinds of charges and attention and so on. On second thought, I might as well have done it myself. It’s just a rectangle with rounded corners and gradually slender shapes.

The rounded rectangle can be achieved with canvas.drawrrect (). To achieve the meteor trailing effect, use the paint#shader property to achieve the gradient effect.

  var gradient = ui.Gradient.linear(
    const Offset(0.0),
    Offset(_meteorWidth, 0),
    <Color>[const Color(0xFFFFFFFF), const Color(0x00FFFFFF)],); _meteorPaint.shader = gradient;Copy the code

We randomly create four groups of meteors.

draw

In order to create a more realistic meteor effect, the horizontal effect is not satisfied, it needs to be reversed Angle.

At first, we planned to draw by y/x=tan(θ). Later, considering the need for animation and various dynamic calculations, we simply used canveas.rotate () and Canveas.translate (), which were more convenient and easier to understand.

  void drawMeteor(_MeteorParam param, Canvas canvas) {
    canvas.save();
    var gradient = ui.Gradient.linear(
      const Offset(0.0),
      Offset(_meteorWidth, 0),
      <Color>[const Color(0xFFFFFFFF), const Color(0x00FFFFFF)],); _meteorPaint.shader = gradient; canvas.rotate(pi * param.radians); canvas.translate(param.translateX, tan(pi *0.1) *_meteorWidth + param.translateY);
    canvas.drawRRect(
        RRect.fromLTRBAndCorners(0.0, _meteorWidth, _meteorHeight,
            topLeft: _radius,
            topRight: _radius,
            bottomRight: _radius,
            bottomLeft: _radius),
        _meteorPaint);
    canvas.restore();
  }
Copy the code

Rotate and translate cannot be reversed. The rotate point is on the left. If the rotate point is on the left, the meteor will not move in a straight line. The effect is as follows:

animation

Reuse the AnimationController at night to animate the animation by constantly changing the translateX value.

class _MeteorParam {
  double translateX;
  double translateY;
  double radians;
  void reset() {
    translateX = 1.0.wp + Random().nextDouble() * 20.0.wp;
    radians = -Random().nextDouble() * 0.07 - 0.05;
    translateY = Random().nextDouble() * 0.5.hp;
  }

  void move() {
    translateX -= 20;
    if (translateX <= 1.0.wp) { reset(); }}}Copy the code

NextDouble () * 20.0. Wp (+ Random().nextdouble () * 20.0. Wp + Random().nextdouble () * 20.0. Reinitialize position when sliding across a screen.

At this point, the dream of fine night and meteor effect is realized, the next preview – cool thunderstorm effect.