Python中秋月圆夜:手把手实现月相可视化,用代码赏千里共婵娟

Python中秋月圆夜:手把手实现月相可视化,用代码赏千里共婵娟

文章目录


📖 引言

中秋节,这个承载着千年文化的传统节日,以其独特的满月寓意着团圆与和谐。我们不妨用Python这门优雅的编程语言,来创造一个富有诗意的中秋节月相可视化器。本文将带您通过代码的艺术,重现天空中月亮的盈亏变化,并在中秋节这个特殊的日子里,为我们的程序增添一抹传统文化的色彩。

在这里插入图片描述

🎯 项目概述

我们将构建一个功能丰富的月相可视化系统,主要包含以下特性:

  • 🔭 精确的天文计算:基于29.53天月相周期的高精度算法
  • 🎨 Web界面生成:自动生成华丽的HTML可视化界面
  • 🌟 视觉特效丰富:星空背景、流星效果、月亮光晕等
  • 📊 多维度展示:时间轴、曲线图、年度概览等四种图表
  • 🏮 中秋文化融入:诗词展示、传统装饰元素

2025_mid_autumn

🛠️ 技术架构解析

# 安装依赖 pip install numpy matplotlib datetime base64 io warnings 

项目结构

moon-phase-visualizer/ ├── moon_calculator.py # 核心计算引擎 ├── generate_html.py # HTML生成器 └── moon_phase_2025_mid_autumn.html # 生成的界面 

💡 实现思路

月相计算核心

月相变化周期是29.53天,选定2025年9月25日作为参考新月。通过计算目标日期与参考点的时间差,结合朔望月周期进行数学建模。

算法的关键是将连续时间变化映射到0-1的月相值:前半周期(新月→满月),后半周期(满月→新月)。

可视化难点

matplotlib中文显示问题通过多字体回退解决:微软雅黑 → 黑体 → 其他系统字体。
月亮绘制用圆形+椭圆阴影实现,阴影宽度根据月相值动态计算。中秋节特效包括多层光晕和星星装饰。

核心模块设计

moon_calculator.py - 核心计算引擎

import numpy as np import matplotlib.pyplot as plt import matplotlib.patches as patches from datetime import datetime, timedelta import math import base64 import io import warnings from matplotlib import rcParams warnings.filterwarnings('ignore')# 设置matplotlib为非交互式后端 plt.switch_backend('Agg')# 优化中文字体设置 plt.rcParams['font.sans-serif']=['Microsoft YaHei','SimHei','Arial Unicode MS','DejaVu Sans'] plt.rcParams['axes.unicode_minus']=FalseclassMoonPhaseCalculator:"""月相计算器类"""def__init__(self):# 月相周期约为29.53天 self.lunar_cycle =29.530588853# 更新参考新月日期(2025年9月25日新月) self.reference_new_moon = datetime(2025,9,25)defget_moon_phase(self, date):"""计算指定日期的月相""" days_since_new_moon =(date - self.reference_new_moon).total_seconds()/(24*3600) cycle_position =(days_since_new_moon % self.lunar_cycle)/ self.lunar_cycle if cycle_position <=0.5: phase = cycle_position *2else: phase =2-(cycle_position *2)return phase defget_moon_age(self, date):"""计算月龄""" days_since_new_moon =(date - self.reference_new_moon).total_seconds()/(24*3600)return days_since_new_moon % self.lunar_cycle defis_mid_autumn_festival(self, date):"""判断是否为中秋节(2025年10月6日)""" mid_autumn_2025 = datetime(2025,10,6)returnabs((date - mid_autumn_2025).days)==0defget_mid_autumn_date(self, year=2025):"""获取指定年份的中秋节日期"""if year ==2025:return datetime(2025,10,6)elif year ==2024:return datetime(2024,9,17)elif year ==2026:return datetime(2026,9,25)else:return datetime(2025,10,6)

核心算法:

  • lunar_cycle = 29.530588853:朔望月精确天数
  • get_moon_phase() 通过时间差和模运算计算月相值
  • 使用 total_seconds() 确保计算精度

可视化渲染类

classWebMoonVisualizer:"""Web版月相可视化器"""def__init__(self): self.calculator = MoonPhaseCalculator()defdraw_moon(self, ax, phase, size=1.0, position=(0,0), is_mid_autumn=False):"""绘制月亮形状""" x, y = position # 绘制月亮基础圆形 circle = patches.Circle((x, y), size, facecolor='lightyellow', edgecolor='gold', linewidth=2) ax.add_patch(circle)# 根据月相绘制阴影部分if phase <0.95: shadow_width = size *2*(1- phase)if shadow_width >0.1: shadow = patches.Ellipse((x + size *0.1, y), shadow_width, size *2, facecolor='darkgray', alpha=0.6) ax.add_patch(shadow)# 中秋节特效if is_mid_autumn:for i inrange(4): halo = patches.Circle((x, y), size *(1.3+ i *0.15), facecolor='orange', alpha=0.12- i *0.03, edgecolor='none') ax.add_patch(halo)# 添加星星装饰 star_positions =[(x - size *2.0, y + size *1.0),(x + size *2.0, y + size *1.0),(x - size *1.8, y - size *1.3),(x + size *1.8, y - size *1.3),]for sx, sy in star_positions: star = patches.RegularPolygon((sx, sy),5, radius=size *0.12, facecolor='gold', alpha=0.9) ax.add_patch(star)defget_phase_name(self, phase):"""获取月相名称"""if phase <0.1:return"新月"elif phase <0.35:return"蛾眉月"elif phase <0.65:return"上弦月"elif phase <0.9:return"盈凸月"else:return"满月"

绘制要点:

  • patches.Circle 绘制月亮基础形状
  • 椭圆阴影模拟月相变化:shadow_width = size * 2 * (1 - phase)
  • 中秋特效:多层光晕 + 五角星装饰
  • 颜色搭配:淡黄底色 + 金色边框
在这里插入图片描述

📊 四种图表实现详解

时间轴图表 - 连续月相展示

defcreate_timeline_chart(self, center_date=None, days=30):"""创建时间轴图表(修复重叠问题)"""if center_date isNone: center_date = datetime(2025,10,6) start_date = center_date - timedelta(days=15) fig, ax = plt.subplots(figsize=(24,12))for i inrange(days): current_date = start_date + timedelta(days=i) phase = self.calculator.get_moon_phase(current_date) is_mid_autumn = self.calculator.is_mid_autumn_festival(current_date) x_pos = i *3.5# 增大间距避免重叠 y_pos =0 self.draw_moon(ax, phase, size=1.0, position=(x_pos, y_pos), is_mid_autumn=is_mid_autumn)# 添加日期标签 ax.text(x_pos,-3.0, current_date.strftime('%m-%d'), ha='center', va='top', fontsize=11, fontweight='bold')# 中秋节特殊标记if is_mid_autumn: ax.text(x_pos,3.5,'2025年中秋节', ha='center', va='bottom', fontsize=14, fontweight='bold', color='red')

实现关键:

  • x_pos = i * 3.5:间距设置避免重叠
  • 24x12大画布确保显示完整
  • 中秋节用红色高亮 + 边框装饰
在这里插入图片描述

月相曲线图 - 数学规律可视化

defcreate_phase_chart(self):"""创建月相图表""" fig, ax = plt.subplots(figsize=(12,8)) ax.set_facecolor('#001133') today = datetime(2025,10,6) dates_range =[today + timedelta(days=i -15)for i inrange(31)] phase_values =[self.calculator.get_moon_phase(d)for d in dates_range] ax.plot(range(31), phase_values,'gold', linewidth=4, marker='o', markersize=6, markerfacecolor='yellow', markeredgecolor='orange') ax.fill_between(range(31), phase_values, alpha=0.3, color='gold')# 重要标记线 ax.axhline(y=1.0, color='red', linestyle='--', alpha=0.8, linewidth=2, label='Full Moon') ax.axhline(y=0.0, color='silver', linestyle='--', alpha=0.8, linewidth=2, label='New Moon') ax.axvline(x=15, color='lime', linestyle=':', alpha=0.8, linewidth=3, label='Mid-Autumn Festival') mid_autumn_phase = self.calculator.get_moon_phase(today) ax.plot(15, mid_autumn_phase,'r*', markersize=15, label=f'Festival Phase({mid_autumn_phase:.2f})')

设计要点:

  • 深蓝背景+ 金色曲线营造夜空效果
  • fill_between 创建填充区域增强视觉效果
  • 水平/垂直参考线标注关键点
  • 红色星标突出中秋节位置
在这里插入图片描述

当前月相图

defcreate_current_moon(self):"""创建当前月相图""" fig, ax = plt.subplots(figsize=(8,8)) ax.set_facecolor('#001133') today = datetime(2025,10,6) phase_today = self.calculator.get_moon_phase(today) is_today_mid_autumn = self.calculator.is_mid_autumn_festival(today) self.draw_moon(ax, phase_today, size=3.0, position=(0,0), is_mid_autumn=is_today_mid_autumn) ax.set_xlim(-6,6) ax.set_ylim(-6,6) ax.set_aspect('equal') ax.axis('off') phase_name = self.get_phase_name(phase_today) title =f'2025 Mid-Autumn Festival Moon Phase - {phase_name}\n{today.strftime("%Y-%m-%d")}\nPhase Value: {phase_today:.3f}'if is_today_mid_autumn: title +='\nHappy Mid-Autumn Festival!' ax.text(0,-5, title, ha='center', va='top', fontsize=14, color='white', fontweight='bold', bbox=dict(boxstyle="round,pad=0.8", facecolor="darkblue", alpha=0.8))

技术特点:

  • 8x8正方形画布保证月亮圆形显示
  • size=3.0 大尺寸突出视觉效果
  • 圆角文本框显示详细信息
在这里插入图片描述

图像Base64编码

deffig_to_base64(self, fig):"""将matplotlib图形转换为base64字符串"""buffer= io.BytesIO() fig.savefig(buffer,format='png', facecolor=fig.get_facecolor(), bbox_inches='tight', dpi=150)buffer.seek(0) image_png =buffer.getvalue()buffer.close() plt.close(fig) graphic = base64.b64encode(image_png)return graphic.decode('utf-8')

要点:

  • 内存缓冲区避免临时文件
  • dpi=150 平衡质量与大小
  • plt.close(fig) 释放内存防止泄漏

🌐 HTML界面生成

generate_html.py - 界面组装器

from moon_calculator import WebMoonVisualizer from datetime import datetime defgenerate_html(): visualizer = WebMoonVisualizer()# 生成图表 mid_autumn_date = datetime(2025,10,6) timeline_fig = visualizer.create_timeline_chart(mid_autumn_date, days=30) timeline_img = visualizer.fig_to_base64(timeline_fig) phase_fig = visualizer.create_phase_chart() phase_img = visualizer.fig_to_base64(phase_fig) current_fig = visualizer.create_current_moon() current_img = visualizer.fig_to_base64(current_fig) annual_fig = visualizer.create_annual_overview() annual_img = visualizer.fig_to_base64(annual_fig)# 获取月相信息 moon_info = visualizer.get_moon_info()

CSS3特效设计

/* 星空背景动画 */@keyframes twinkle{0%, 100%{opacity: 0.3;}50%{opacity: 1;}}/* 流星效果 */@keyframes shooting{0%{transform:rotate(-45deg)translateX(0)translateY(0);opacity: 1;}100%{transform:rotate(-45deg)translateX(-800px)translateY(800px);opacity: 0;}}/* 月亮背景浮动 */@keyframes float{0%, 100%{transform:translateY(0px);}50%{transform:translateY(-15px);}}/* 渐变文字效果 */.highlight{background:linear-gradient(45deg, #ff6b35, #f7931e, #ffd700);-webkit-background-clip: text;-webkit-text-fill-color: transparent;animation: gradient-shift 3s ease infinite;}
在这里插入图片描述

JavaScript交互特效

// 创建120颗星星functioncreateStars(){const starsContainer = document.getElementById('stars');const numberOfStars =120;for(let i =0; i < numberOfStars; i++){const star = document.createElement('div'); star.className ='star'; star.style.left = Math.random()*100+'%'; star.style.top = Math.random()*100+'%';const size = Math.random()*3+1; star.style.width = size +'px'; star.style.height = size +'px'; star.style.animationDelay = Math.random()*3+'s'; starsContainer.appendChild(star);}}// 流星效果functioncreateShootingStar(){const shootingStar = document.createElement('div'); shootingStar.className ='shooting-star';const startX = Math.random()* window.innerWidth;const startY = Math.random()*(window.innerHeight *0.5); shootingStar.style.left = startX +'px'; shootingStar.style.top = startY +'px'; shootingStar.style.animation ='shooting 1.5s linear forwards'; document.body.appendChild(shootingStar);setTimeout(()=>{ shootingStar.remove();},1500);}

特效实现:

  • 120颗随机分布的闪烁星星
  • 流星从随机位置斜向划过
  • 自动清理DOM防止内存泄漏

🌟 结语

正如古人所言:"但愿人长久,千里共婵娟。"愿我们的代码也能像这轮明月一样,在技术的夜空中永远闪耀着智慧的光芒,连接着传统与未来,架起文化与科技的桥梁。

中秋节快乐!代码如明月,永远照亮前行的路!🌕🥮


本项目代码已在github开源分享,欢迎大家folk和star!https://github.com/yan-6/python_project/tree/2025mid_autumn?tab=readme-ov-file

在这里插入图片描述

Read more

【OpenClaw从入门到精通】第10篇:OpenClaw生产环境部署全攻略:性能优化+安全加固+监控运维(2026实测版)

【OpenClaw从入门到精通】第10篇:OpenClaw生产环境部署全攻略:性能优化+安全加固+监控运维(2026实测版)

摘要:本文聚焦OpenClaw从测试环境走向生产环境的核心痛点,围绕“性能优化、安全加固、监控运维”三大维度展开实操讲解。先明确生产环境硬件/系统选型标准,再通过硬件层资源管控、模型调度策略、缓存优化等手段提升响应速度(实测响应效率提升50%+);接着从网络、权限、数据三层构建安全防护体系,集成火山引擎安全方案拦截高危操作;最后落地TenacitOS可视化监控与Prometheus告警体系,配套完整故障排查清单和虚拟实战案例。全文所有配置、代码均经实测验证,兼顾新手入门实操性和进阶读者的生产级部署需求,帮助开发者真正实现OpenClaw从“能用”到“放心用”的跨越。 优质专栏欢迎订阅! 【DeepSeek深度应用】【Python高阶开发:AI自动化与数据工程实战】【YOLOv11工业级实战】 【机器视觉:C# + HALCON】【大模型微调实战:平民级微调技术全解】 【人工智能之深度学习】【AI 赋能:Python 人工智能应用实战】【数字孪生与仿真技术实战指南】 【AI工程化落地与YOLOv8/v9实战】【C#工业上位机高级应用:高并发通信+性能优化】 【Java生产级避坑指南:

By Ne0inhk
ARM Linux 驱动开发篇--- Linux 并发与竞争实验(互斥体实现 LED 设备互斥访问)--- Ubuntu20.04互斥体实验

ARM Linux 驱动开发篇--- Linux 并发与竞争实验(互斥体实现 LED 设备互斥访问)--- Ubuntu20.04互斥体实验

🎬 渡水无言:个人主页渡水无言 ❄专栏传送门: 《linux专栏》《嵌入式linux驱动开发》《linux系统移植专栏》 ❄专栏传送门: 《freertos专栏》《STM32 HAL库专栏》 ⭐️流水不争先,争的是滔滔不绝  📚博主简介:第二十届中国研究生电子设计竞赛全国二等奖 |国家奖学金 | 省级三好学生 | 省级优秀毕业生获得者 | ZEEKLOG新星杯TOP18 | 半导纵横专栏博主 | 211在读研究生 在这里主要分享自己学习的linux嵌入式领域知识;有分享错误或者不足的地方欢迎大佬指导,也欢迎各位大佬互相三连 目录 前言  一、实验基础说明 1.1、互斥体简介 1.2 本次实验设计思路 二、硬件原理分析(看过之前博客的可以忽略) 三、实验程序编写 3.1 互斥体 LED 驱动代码(mutex.c) 3.2.1、设备结构体定义(28-39

By Ne0inhk
Flutter for OpenHarmony:swagger_dart_code_generator 接口代码自动化生成的救星(OpenAPI/Swagger) 深度解析与鸿蒙适配指南

Flutter for OpenHarmony:swagger_dart_code_generator 接口代码自动化生成的救星(OpenAPI/Swagger) 深度解析与鸿蒙适配指南

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net 前言 后端工程师扔给你一个 Swagger (OpenAPI) 文档地址,你会怎么做? 1. 对着文档,手写 Dart Model 类(容易写错字段类型)。 2. 手写 Retrofit/Dio 的 API 接口定义(容易拼错 URL)。 3. 当后端修改了字段名,你对着报错修半天。 这是重复劳动的地狱。 swagger_dart_code_generator 可以将 Swagger (JSON/YAML) 文件直接转换为高质量的 Dart 代码,包括: * Model 类:支持 json_serializable,带 fromJson/

By Ne0inhk
Linux 开发别再卡壳!makefile/git/gdb 全流程实操 + 作业解析,新手看完直接用----《Hello Linux!》(5)

Linux 开发别再卡壳!makefile/git/gdb 全流程实操 + 作业解析,新手看完直接用----《Hello Linux!》(5)

文章目录 * 前言 * make/makefile * 文件的三个时间 * Linux第一个小程序-进度条 * 回车和换行 * 缓冲区 * 程序的代码展示 * git指令 * 关于gitee * Linux调试器-gdb使用 * 作业部分 前言 做 Linux 开发时,你是不是也遇到过这些 “卡脖子” 时刻?写 makefile 时,明明语法没错却报错,最后发现是依赖方法行没加 Tab;想提交代码到 gitee,记不清 git add/commit/push 的 “三板斧”,还得反复搜教程;用 gdb 调试程序,输了命令没反应,才想起编译时没加-g生成 debug 版本;甚至连写个进度条,都搞不懂\r和\n的区别,导致进度条乱跳…… 其实这些问题,

By Ne0inhk