HarmonyOS应用《玄象》开发实战:MoonPhasesPage 月相页:Date 时间轴 + 月相 Canvas 球面光照算法

📅 2026/7/27 10:55:46
HarmonyOS应用《玄象》开发实战:MoonPhasesPage 月相页:Date 时间轴 + 月相 Canvas 球面光照算法
阅读时长约 19 分钟 | 难度★★★★★ | 篇章第 8 篇 · 天文历法模块 对应源码entry/src/main/ets/pages/astronomy/MoonPhasesPage.ets前言月相展示是玄象项目天文历法模块的视觉亮点。页面通过 Canvas 绘制 8 种月相新月→满月→残月的球面光照阴影并通过进度条让用户选择查看不同月相。本篇将深入剖析玄象项目月相页的实现从MoonPhase数据结构、Canvas球面光照算法、arc明暗界线绘制到月相进度条交互。掌握这套月相绘制算法您就能为任何 HarmonyOS 应用构建逼真的月相展示。提示玄象项目月相绘制采用“圆弧切割“算法模拟月球明暗界线。一、月相数据1.1 八种月相private phases: MoonPhase[] [ { name: 新月, day: 初一 }, { name: 蛾眉月, day: 初三 }, { name: 上弦月, day: 初七 }, { name: 盈凸月, day: 十二 }, { name: 满月, day: 十五 }, { name: 亏凸月, day: 十八 }, { name: 下弦月, day: 廿二 }, { name: 残月, day: 廿七 } ];二、Canvas 月相绘制2.1 球面光照算法private drawMoon(canvas: CanvasRenderingContext2D, w: number, h: number): void { const cx w / 2, cy h / 2; const r Math.min(w, h) / 2 - 10; // 背景暗面 canvas.fillStyle #1A1A2E; canvas.beginPath(); canvas.arc(cx, cy, r, 0, Math.PI * 2); canvas.fill(); // 亮面根据月相计算明暗界线 const phase this.currentPhase; canvas.fillStyle #F0D078; canvas.beginPath(); if (phase 0) { // 新月 // 不绘制亮面 } else if (phase 4) { // 满月 canvas.arc(cx, cy, r, 0, Math.PI * 2); canvas.fill(); } else { // 半圆 椭圆弧 const xOffset r * (1 - phase / 4); canvas.arc(cx, cy, r, -Math.PI / 2, Math.PI / 2); canvas.ellipse(cx, cy, r, xOffset, 0, Math.PI / 2, -Math.PI / 2); canvas.fill(); } }三、月相进度条3.1 迷你月相ForEach(this.phases, (phase: MoonPhase, index: number) { Column({ space: 4 }) { Canvas(this.drawMiniMoon.bind(this, index)) .width(36).height(36) Text(phase.name) .fontSize(10) .fontColor(index this.currentPhase ? Colors.PRIMARY_GOLD : Colors.TEXT_DIM) } })四、月相页设计总结4.1 页面结构区域组件内容月相图Canvas220×220 月相绘制月相名称Text当前月相名农历日期Text对应农历日月相进度条Row8 个迷你月相总结本篇以玄象项目月相页为蓝本深入剖析了 Canvas 月相绘制算法从MoonPhase数据结构、Canvas球面光照算法、arc明暗界线绘制到月相进度条交互。掌握这套月相绘制算法您就能为任何 HarmonyOS 应用构建逼真的月相展示。如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力相关资源月相wikipedia.org/wiki/月相开源鸿蒙跨平台社区https://openharmonycrossplatform.csdn.net