Farmers in yards world, beautiful application experience, from the programmer for the processing of detail, and self requirements state, agriculture in the yard a member of the young people is busy, every day, every week, can leave some footprints, is the creation of content, there is a persistent, is I don’t know why, if you lost, might as well to Chou Chou code track of farmers.

  • Beautiful musical beats take you through the coding process of this effect
  • Insist on every day, is the pursuit of every ideal youth
  • Follow in the footsteps of young people, and maybe your answer is right here

The effect achieved in this article is shown in the figure below:

/// program entry
void main(a) {
  runApp(
    MaterialApp(
      // Do not display the debug tag
      debugShowCheckedModeBanner: false.// The first page is displayed by default
      home: TestPage(),
    ),
  );
}
Copy the code

Let’s start with a global method to get random transparency of the white color, which is used to generate different white colors for snowflakes:

// Globally define the method to get the color
Color getRandomWhiteColor(Random random) {
  // Transparency 0 to 200 255 is opaque
  int a = random.nextInt(200);
  return Color.fromARGB(a, 255.255.255);
}
Copy the code

Define the snowflake model to store the basic attribute information of snowflakes:

/// Define a snowflake model to store basic information about snowflakes
class BobbleBean {
  / / position
  Offset postion;

  // The initial position
  Offset origin;
  / / color
  Color color;
  // The speed of movement
  double speed;
  / / radius
  double radius;
}
Copy the code
/// snowflake background
class TestPage extends StatefulWidget {
  @override
  _TestPageState createState(a) => _TestPageState();
}

class _TestPageState extends State<TestPage> with TickerProviderStateMixin {
  // Create a collection to hold bubbles
  List<BobbleBean> _list = [];

  / / random number
  Random _random = new Random(DateTime.now().microsecondsSinceEpoch);

  // Create an animation controller
  AnimationController _animationController;

  // Create bubbles in the initializer function
  @override
  void initState(a) {
    super.initState();

    Future.delayed(Duration.zero, () {
      initData();
    });

    // Create the animation controller for 1 second
    _animationController = new AnimationController(
        vsync: this, duration: Duration(milliseconds: 10000));

    // Perform refresh listening
    _animationController.addListener(() {
      setState(() {});
    });
    // Turn on the bubble movement
    _animationController.repeat();

    // Status bar hidden
    SystemChrome.setEnabledSystemUIOverlays([]);
  }

  void initData(a) {
    for (int i = 0; i < 2000; i++) {
      BobbleBean bean = new BobbleBean();
      // Get random transparency white
      bean.color = getRandomWhiteColor(_random);
      // Set the position to the default drawing position and then change it
      double x = _random.nextDouble() * MediaQuery.of(context).size.width;
      double y = _random.nextDouble() * MediaQuery.of(context).size.height;
      double z = _random.nextDouble() + 0.5;
      bean.speed = _random.nextDouble() + 0.01 / z;
      bean.postion = Offset(x, y);
      bean.origin = Offset(x, 0);
      // Set the radius
      bean.radius = 2.0/ z; _list.add(bean); }}... . }Copy the code

The page UI is constructed as follows:


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,

      /// Fill the layout
      body: Container(
        width: double.infinity,
        height: double.infinity,
        // Cascading layout
        child: Stack(
          children: [
            // Part 1 background
            Positioned.fill(
              child: Image.asset(
                "assets/images/bg_snow.png",
                fit: BoxFit.fill,
              ),
            ),
            // Part 2 Snowflakes
            CustomPaint(
              size: MediaQuery.of(context).size,
              / / the canvas
              painter: SnowCustomMyPainter(list: _list, random: _random),
            ),
          ],
        ),
      ),
    );
  }
Copy the code

The custom canvas is as follows:

/// Create canvas
class SnowCustomMyPainter extends CustomPainter {
  List<BobbleBean> list;
  Random random;

  SnowCustomMyPainter({this.list, this.random}); 

  // Start with a brush
  Paint _paint = newPaint().. isAntiAlias =true;
  // Specify the drawing function
  @override
  void paint(Canvas canvas, Size size) {
    // Recalculate the position of each point before drawing
    list.forEach((element) {
      // Left and right slightly jitter
      double dx = random.nextDouble() * 2.0 - 1.0;
      // The vertical position is offset
      double dy = element.speed;
      // Calculate the position offset
      element.postion += Offset(dx, dy);

      // Reset the position
      if(element.postion.dy > size.height) { element.postion = element.origin; }});//
    / / / / map
    list.forEach((element) {
      // Change the color of the brush
      _paint.color = element.color;
      / / draw circle
      canvas.drawCircle(element.postion, element.radius, _paint);
    });
  }

  // Refresh control
  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    // Return false not to refresh
    return true; }}Copy the code

[X1] Daily reminder of wechat public account at any time, daily accumulation, free to follow the bottom of the article scan code attention

【 X2 】 Various series of free open source video tutorials focus on you won’t get lost

【 X3 】 series article millions of Demo copy and paste use at any time

[X4] Short video is not the same experience

[x5] must have source code


Not limited to thinking, not limited to language restrictions, is the highest realm of programming.

With xiaobian character, must be to record a set of video, and then upload

If you are interested, you can check out the watermelon video – early risers