在码农的世界里,优美的应用体验,来源于程序员对细节的处理以及自我要求的境界,年轻人也是忙忙碌碌的码农中一员,每天、每周,都会留下一些脚印,就是这些创作的内容,有一种执着,就是不知为什么,如果你迷茫,不妨来瞅瞅码农的轨迹。
本文章实现的效果如下图所示:
/// 程序入口
void main() {
  runApp(
    MaterialApp(
      //不显示debug标签
      debugShowCheckedModeBanner: false,
      //默认显示的首页面
      home: TestPage(),
    ),
  );
}首先来一个全局获取随机透明度的白色颜色的方法,用来生成雪花使用的不同的白色:
//全局定义获取颜色的方法
Color getRandomWhiteColor(Random random) {
  //透明度 0 ~ 200  255是不透明
  int a = random.nextInt(200);
  return Color.fromARGB(a, 255, 255, 255);
}定义 雪花模型 用来保存雪花的基本属性信息:
///定义 雪花模型 用来保存雪花的基本属性信息
class BobbleBean {
  //位置
  Offset postion;
  //初始位置
  Offset origin;
  //颜色
  Color color;
  //运动的速度
  double speed;
  //半径
  double radius;
}/// 雪花背景
class TestPage extends StatefulWidget {
  @override
  _TestPageState createState() => _TestPageState();
}
class _TestPageState extends State<TestPage> with TickerProviderStateMixin {
  //创建一个集合用来保存气泡
  List<BobbleBean> _list = [];
  //随机数
  Random _random = new Random(DateTime.now().microsecondsSinceEpoch);
  //来个动画控制器
  AnimationController _animationController;
  //初始化函数中创建气泡
  @override
  void initState() {
    super.initState();
    Future.delayed(Duration.zero, () {
      initData();
    });
    //创建动画控制器 1秒
    _animationController = new AnimationController(
        vsync: this, duration: Duration(milliseconds: 10000));
    //执行刷新监听
    _animationController.addListener(() {
      setState(() {});
    });
    //开启气泡的运动
    _animationController.repeat();
    // 状态栏隐藏
    SystemChrome.setEnabledSystemUIOverlays([]);
  }
  void initData() {
    for (int i = 0; i < 2000; i++) {
      BobbleBean bean = new BobbleBean();
      //获取随机透明度白色
      bean.color = getRandomWhiteColor(_random);
      //设置位置 先来个默认的 绘制的时候再修改
      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);
      //设置半径
      bean.radius = 2.0 / z;
      _list.add(bean);
    }
  }
  ... ...
}页面 UI 的构建方法如下:
@override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      ///填充布局
      body: Container(
        width: double.infinity,
        height: double.infinity,
        //层叠布局
        child: Stack(
          children: [
            //第一部分 背景
            Positioned.fill(
              child: Image.asset(
                "assets/images/bg_snow.png",
                fit: BoxFit.fill,
              ),
            ),
            //第二部分 雪花
            CustomPaint(
              size: MediaQuery.of(context).size,
              //画布
              painter: SnowCustomMyPainter(list: _list, random: _random),
            ),
          ],
        ),
      ),
    );
  }自定义画布如下:
///创建画布
class SnowCustomMyPainter extends CustomPainter {
  List<BobbleBean> list;
  Random random;
  SnowCustomMyPainter({this.list, this.random}); 
  //先来个画笔
  Paint _paint = new Paint()..isAntiAlias = true;
  //具体的绘制功能
  @override
  void paint(Canvas canvas, Size size) {
    // 在绘制前重新计算每个点的位置
    list.forEach((element) {
      //左右微抖动
      double dx = random.nextDouble() * 2.0 - 1.0;
      //竖直方向位置偏移
      double dy = element.speed;
      //位置偏移量计算
      element.postion += Offset(dx, dy);
      //重置位置
      if (element.postion.dy > size.height) {
        element.postion = element.origin;
      }
    });
    //
    // //绘制
    list.forEach((element) {
      //修改画笔的颜色
      _paint.color = element.color;
      //绘制圆
      canvas.drawCircle(element.postion, element.radius, _paint);
    });
  }
  //刷新 控制
  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    //返回false 不刷新
    return true;
  }
}
Flutter 雪花飘落的效果 冬秋的延续 雪是冬的足迹 我们共同努力
不局限于思维,不局限语言限制,才是编程的最高境界。
以小编的性格,肯定是要录制一套视频的,随后会上传










