页面预览

阅读时长:约 19 分钟 | 难度:★★★★★ | 篇章:第 8 篇 · 天文历法模块
对应源码:entry/src/main/ets/pages/astronomy/MoonPhasesPage.ets

月相页Canvas球面光照算法

前言

月相展示是玄象项目天文历法模块的视觉亮点。页面通过 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 页面结构

区域 组件 内容
月相图 Canvas 220×220 月相绘制
月相名称 Text 当前月相名
农历日期 Text 对应农历日
月相进度条 Row 8 个迷你月相

总结

本篇以玄象项目月相页为蓝本,深入剖析了 Canvas 月相绘制算法:从 MoonPhase 数据结构、Canvas 球面光照算法、arc 明暗界线绘制,到月相进度条交互。掌握这套月相绘制算法,您就能为任何 HarmonyOS 应用构建逼真的月相展示。

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐