当前位置: 首页 > news >正文

月相小组件:鸿蒙Flutter框架 实现的月相显示应用

欢迎加入开源鸿蒙跨平台社区:
https://openharmonycrossplatform.csdn.net



1. 项目介绍

月相是地球上看到的月球表面被太阳照明部分的形状,它随着月球绕地球运行而变化。月相小组件是一个基于 Flutter 开发的应用,它能够显示当前日期的月相、月龄和照明度,并且支持用户选择不同的日期查看对应的月相。本文将详细介绍如何使用 Flutter 实现这个实用的月相显示应用。

1.1 项目目标

  • 实现一个显示月相的应用
  • 计算并显示月龄和照明度
  • 支持选择不同日期查看月相
  • 显示月相阶段的详细说明
  • 采用美观的界面设计,模拟夜空效果
  • 确保在不同平台上的一致性表现

1.2 技术栈

  • Flutter:跨平台 UI 框架
  • Dart:编程语言
  • StatefulWidget:用于管理应用状态
  • math:用于计算月相的数学算法
  • intl:用于格式化日期
  • Stack 和 Positioned:用于实现月相的视觉效果
  • LinearGradient:用于实现渐变背景

2. 核心功能设计

2.1 月相计算

  • 月相算法:基于 J2000 纪元的月球轨道参数计算月相
  • 月龄计算:计算月球从新月开始的天数
  • 照明度计算:计算月球表面被太阳照明的百分比
  • 月相阶段:根据月龄确定月相阶段(新月、娥眉月、上弦月、盈凸月、满月、亏凸月、下弦月、残月)

2.2 日期选择

  • 日期选择器:使用 showDatePicker 实现日期选择功能
  • 日期范围:支持选择 1900 年到 2100 年之间的日期
  • 日期格式:使用 yyyy年MM月dd日 格式显示日期

2.3 月相显示

  • 月球可视化:使用圆形容器和渐变背景模拟月球
  • 月相遮罩:根据月相阶段显示不同的遮罩,模拟月相的视觉效果
  • 阴影效果:添加阴影效果,增强月球的立体感

2.4 月相信息

  • 月相名称:显示当前月相的名称
  • 月龄:显示月球从新月开始的天数
  • 照明度:显示月球表面被太阳照明的百分比
  • 月相说明:显示当前月相阶段的详细说明

2.5 界面设计

  • 夜空背景:使用深蓝色渐变背景,模拟夜空效果
  • 响应式设计:适应不同屏幕尺寸
  • 简洁布局:布局清晰,信息一目了然
  • 视觉效果:使用阴影和渐变增强视觉效果

3. 技术架构

3.1 项目结构

lib/ └── main.dart # 主应用文件,包含所有代码

3.2 组件结构

MoonPhaseApp └── MoonPhaseScreen ├── State management (_selectedDate, _currentMoonPhase, _moonAge, _illumination) ├── Moon phase calculation (_calculateMoonPhase) ├── Date selection (_selectDate) ├── UI components │ ├── Date picker button │ ├── Moon visualization (_buildMoonPhaseMask) │ ├── Moon phase information │ └── Moon phase description └── Helper methods ├── _getMoonPhaseName └── _getMoonPhaseDescription

3.3 数据模型

  • 选中日期DateTime类型,存储用户选择的日期
  • 当前月相MoonPhase枚举类型,存储当前月相阶段
  • 月龄double类型,存储月球从新月开始的天数
  • 照明度double类型,存储月球表面被太阳照明的百分比

4. 关键代码解析

4.1 月相计算

void_calculateMoonPhase(DateTimedate){// 计算月相的核心算法// 基于J2000纪元的月球轨道参数finalepoch=DateTime.utc(2000,1,6,18,14,0);// 2000年1月6日是新月finaldaysSinceEpoch=date.difference(epoch).inDays+(date.hour+date.minute/60+date.second/3600)/24;finallunarCycle=29.530588853;// 月球公转周期(天)_moonAge=daysSinceEpoch%lunarCycle;finalphaseAngle=(2*pi*_moonAge)/lunarCycle;// 计算月球照明百分比_illumination=(1-cos(phaseAngle))/2;// 确定月相finalphase=_moonAge/lunarCycle;if(phase<0.0625){_currentMoonPhase=MoonPhase.newMoon;}elseif(phase<0.25){_currentMoonPhase=MoonPhase.waxingCrescent;}elseif(phase<0.3125){_currentMoonPhase=MoonPhase.firstQuarter;}elseif(phase<0.5){_currentMoonPhase=MoonPhase.waxingGibbous;}elseif(phase<0.5625){_currentMoonPhase=MoonPhase.fullMoon;}elseif(phase<0.75){_currentMoonPhase=MoonPhase.waningGibbous;}elseif(phase<0.8125){_currentMoonPhase=MoonPhase.lastQuarter;}else{_currentMoonPhase=MoonPhase.waningCrescent;}setState((){});}

代码解析

  • _calculateMoonPhase方法:计算月相的核心方法
  • 基于 2000 年 1 月 6 日(新月)作为纪元
  • 计算从纪元到选定日期的天数
  • 根据月球公转周期(29.530588853 天)计算月龄
  • 根据月龄计算月相阶段和照明度
  • 使用setState更新界面

4.2 日期选择

void_selectDate()async{finalDateTime?picked=awaitshowDatePicker(context:context,initialDate:_selectedDate,firstDate:DateTime(1900),lastDate:DateTime(2100),);if(picked!=null&&picked!=_selectedDate){setState((){_selectedDate=picked;_calculateMoonPhase(_selectedDate);});}}

代码解析

  • _selectDate方法:打开日期选择器,让用户选择日期
  • 使用showDatePicker显示日期选择器
  • 日期范围设置为 1900 年到 2100 年
  • 选择日期后,更新_selectedDate并重新计算月相

4.3 月相显示

Widget_buildMoonPhaseMask(){switch(_currentMoonPhase){caseMoonPhase.newMoon:returnContainer(width:200,height:200,decoration:BoxDecoration(shape:BoxShape.circle,color:Colors.blue.shade900,),);caseMoonPhase.waxingCrescent:returnPositioned(right:0,child:Container(width:100,height:200,decoration:BoxDecoration(color:Colors.blue.shade900,borderRadius:constBorderRadius.only(topRight:Radius.circular(100),bottomRight:Radius.circular(100),),),),);caseMoonPhase.firstQuarter:returnPositioned(right:0,child:Container(width:100,height:200,decoration:BoxDecoration(color:Colors.blue.shade900,borderRadius:constBorderRadius.only(topRight:Radius.circular(100),bottomRight:Radius.circular(100),),),),);caseMoonPhase.waxingGibbous:returnPositioned(right:0,child:Container(width:50,height:200,decoration:BoxDecoration(color:Colors.blue.shade900,borderRadius:constBorderRadius.only(topRight:Radius.circular(100),bottomRight:Radius.circular(100),),),),);caseMoonPhase.fullMoon:returnContainer();caseMoonPhase.waningGibbous:returnPositioned(
http://www.jsqmd.com/news/614603/

相关文章:

  • HTML5 标题
  • 装修甲醛最大的隐形坑:90% 的人都忽略了墙面基层
  • 彻底告别OpenClaw使用焦虑:我给他装上了“透视眼”和“批量克隆模组寐
  • OpenClaw跨平台安全:Windows下用SecGPT-14B分析恶意文档
  • STM32使用模拟I2C读取AT24C02数据
  • 告别重复编码!IDEA 集成通义灵码 / Trae,让 AI 成为你的开发副驾
  • 别再数据线了!用FastAPI 分钟搭个局域网文件+剪贴板神器志
  • FastAPI项目半夜报警吵醒你?聊聊告警这事儿怎么搞!偷
  • # 010、AutoSAR CP基础软件(BSW)模块详解:ECU抽象层
  • 核心商业机密总在不经意间流失?这六个小妙招教给你,守护机密文件
  • 西门子1200plc485轮询读写28个测试仪表,包括plc程序和触摸屏程序,仪表485通讯协...
  • golang如何集成Consul KV配置管理_golang Consul KV配置管理集成要点
  • 主席树,区间第k小 / 第k大 / 区间小于x的数的个数 等
  • HTML 5段落
  • 电容是什么?一个“快充快放”的微型充电宝趟
  • 从 0 到可用:我用这套方式把 AI 编程工具快速跑通(少走弯路版)
  • 进程与线程的核心区别:一篇看懂,告别混淆
  • 我看出来了,这里的空间弯曲本质并不需要弯曲到第三个维度,而单纯就是一个平面上的伸缩就可以,那么如果说这个二维平面整体成奇点了代表什么
  • 不满意Oh My Zsh启动卡顿,来试试Starship吧艘
  • 如何一键导入「阅读」APP书源:3种方法+26个高质量书源全解析
  • 如何评估 AI 数据分析工具?CTO 必看的选型维度清单
  • HagiCode Soul 平台技术解析:从需求萌发到独立平台的演进之路烤
  • 出厂自带“缰绳”的AI来了,Hermes Agent正在重新定义智能体
  • 2026年苏州扶梯链条厂家最新推荐榜单:苏州梯级链条、踏板链条、人行道链条、驱动链条、回转链条、压带链条厂家选择指南,专精企业精选 - 海棠依旧大
  • 2026 年前端主流开发技术全景指南
  • .NET源码生成器基于partial范式开发和nuget打包匮
  • 神经网络中的“偏置”究竟是做什么的?为什么几乎所有公式里都有它?
  • 突破4大下载瓶颈:开源工具如何让云存储速度提升500%
  • 设计模式之责任链模式
  • 八大网盘直链下载助手终极指南:免费获取真实下载地址,告别客户端限速烦恼