Skip to content

Astronomy Engine 使用指南

Astronomy Engine 是一个高精度的天文计算 JavaScript 库,支持浏览器和 Node.js 环境。本文档记录乙巳观(道由天观)中它的使用方式。

📦 项目集成信息

当前版本

🚀 项目中的实际应用

utils/celestial.ts 天体坐标层

项目中所有天体位置计算集中在 utils/celestial.ts,astronomy-engine 在此完成从 JavaScript Date 到黄经/赤经/距离的精确换算:

typescript
// src/utils/celestial.ts 中的典型使用
import { AstroTime, SunPosition, MakeTime } from 'astronomy-engine'

/**
 * 太阳真实黄经(度)
 * 春分点 0°、夏至 90°、秋分 180°、冬至 270°
 */
export const sunLongitude = (time: Date): number => {
  try {
    const astroTime = MakeTime(time)
    const sunEcliptic = SunPosition(astroTime)
    return sunEcliptic.elon
  } catch (error) {
    console.warn('计算太阳位置失败,回退到简单公式:', error)
    // 简单近似(每日 ~0.9856°,冬至偏移 ~280°)
    const yearStart = new Date(time.getFullYear(), 0, 1)
    const dayOfYear = Math.floor((time.getTime() - yearStart.getTime()) / 86_400_000)
    return (dayOfYear * 360 / 365.25 + 280) % 360
  }
}

上层组件(如 SevenLuminariesRingMoonPhaseRingBeidouCenter)只调用 utils/celestial.tsutils/planetMansion.ts 暴露的纯函数,不直接接触 astronomy-engine,从而保证时间驱动的响应式链完整、组件层保持纯渲染。

🎯 核心功能实现

1. 太阳黄经计算

项目主要使用 SunPosition 函数计算太阳的黄道坐标:

typescript
const sunEcliptic = SunPosition(astroTime)
const longitude = sunEcliptic.elon  // 黄经,单位:度数

特点:

  • 返回度数而非弧度,便于直接使用
  • 高精度计算,误差极小
  • 自动处理时间转换

2. 时间处理

使用 MakeTime 函数将 JavaScript Date 转换为天文时间:

typescript
// 转换JavaScript Date为Astronomy Time
const astroTime = MakeTime(new Date())

// 或者使用AstroTime构造函数
const astroTime2 = new AstroTime(new Date())

3. 实时更新机制

Vue 响应式 + time prop 的组合是全项目统一范式。举例——七曜环:

vue
<template>
  <SevenLuminariesRing
    :radius="380"
    :inner-radius="340"
    :time="controlledTime"
  />
</template>

<script setup>
import { ref, computed, unref } from 'vue'

// 响应式时间变量
const controlledTime = ref(new Date())

// SevenLuminariesRing 内部:所有位置派生自 timeRef computed
// const timeRef = computed(() => unref(props.time) ?? new Date())
// const positions = computed(() => planetPositions(timeRef.value))
</script>

🌍 项目特色功能

1. 七曜入宿实时计算

utils/planetMansion.ts 把太阳、月亮、水金火木土五星的赤经映射到二十八宿区间,配合 useSevenLuminaries composable 在 SevenLuminariesRingSkyChart 中实时点亮当日入宿。

2. 五星会合周期计算

utils/conjunctions.ts 利用 astronomy-engine 的二分搜索(SearchRelativeLongitude)计算任意两颗行星的会合时间点。模块级 Map 缓存(FIFO 淘汰,max=100)避免同一窗口重复查询。ConjunctionCyclesView 消费此工具,绘制五星会合赤经序列连线图。

3. 岁差修正的北斗指向

utils/beidou.ts 用 astronomy-engine 计算北斗七星在指定时刻的真实赤经赤纬(含 J2000 岁差修正),BeidouCenterSuzhouSkyMap 都从这里取数,让斗柄随本地恒星时旋转,正确指向所值宿。

4. 月相几何绘制

utils/moonPhase.ts 把 astronomy-engine 计算的月相角转成 SVG 弧段参数,MoonPhaseRing 直接消费——当日月相形状、明暗方向都由时间派生。

5. 与极坐标系统的集成

所有位置都用统一的极坐标工具 utils/geometry.tspolarToCartesian 转换,避免各组件重复写三角函数:

typescript
import { polarToCartesian } from '@/utils/geometry'

// 把赤经 ra 映射为盘面角度(天星版约定:angle = 360 - ra)
const { x, y } = polarToCartesian(radius, 360 - ra)

🎮 与 Sidebar 面板的集成

天体环通过 time prop 与视图内的 controlledTime 挂钩,Sidebar 面板通过 useCompassContext 统一读写这份时间:

vue
<!-- View 侧 -->
<script setup lang="ts">
import { useUrlTime } from '@/composables/useUrlTime'
import { useViewport } from '@/composables/useViewport'
import { provideCompassContext } from '@/composables/useCompassContext'
import SevenLuminariesRing from '@/components/rings/SevenLuminariesRing.vue'

const { controlledTime, clearUrlTime } = useUrlTime()
const viewport = useViewport()

provideCompassContext({
  time: controlledTime,
  viewport,
  onUserTimeChange: () => clearUrlTime()
})
</script>

<template>
  <SevenLuminariesRing
    :radius="380"
    :inner-radius="340"
    :time="controlledTime"
  />
</template>

Sidebar(CompassSidebar.vue,由 CompassLayout 单点挂载)内部通过 useCompassContext() 读取当前 View 的 time / viewport,用户可以:

  • 调整时间查看天体位置变化(TimePanel)
  • 播放动画观察天体运动(useTimeController + Space 快捷键)
  • 调整播放速度
  • 使用键盘快捷键控制(useTimeShortcuts / useViewportShortcuts

🔧 安装和配置

当前项目配置

项目已正确配置 astronomy-engine:

json
// package.json
{
  "dependencies": {
    "astronomy-engine": "^2.1.19"
  }
}

VitePress SSR 内联

astronomy-engine 是 CJS 模块,SSR 阶段需要交给 Vite 内联,避免 dev/build 边界问题:

ts
// docs/.vitepress/config.ts
vite: {
  ssr: {
    noExternal: ['astronomy-engine', 'tyme4ts'],
  },
}

TypeScript 配置

项目使用 TypeScript,类型定义已自动包含。

📚 扩展使用建议

1. 月球位置

typescript
import { MoonPosition, MakeTime } from 'astronomy-engine'

export const moonPosition = (time: Date) => {
  const astroTime = MakeTime(time)
  const moon = MoonPosition(astroTime)
  return {
    longitude: moon.geo_eclip_lon,
    latitude: moon.geo_eclip_lat,
    distance: moon.distance_au
  }
}

2. 行星位置

typescript
import { Body, GeoVector, Ecliptic } from 'astronomy-engine'

export const planetPosition = (planet: Body, time: Date) => {
  const vec = GeoVector(planet, time, true)
  const ecl = Ecliptic(vec)
  return {
    longitude: ecl.elon,
    latitude: ecl.elat,
    distance: Math.hypot(vec.x, vec.y, vec.z)
  }
}

3. 日月食预测

typescript
import { SearchLunarEclipse, SearchGlobalSolarEclipse } from 'astronomy-engine'

export const findNextEclipse = (startDate: Date) => {
  return {
    lunar: SearchLunarEclipse(startDate),
    solar: SearchGlobalSolarEclipse(startDate)
  }
}

🐛 错误处理和后备方案

项目在 utils/celestial.ts 层统一处理 try-catch,业务组件不用重复:

typescript
export const sunLongitude = (time: Date): number => {
  try {
    return SunPosition(MakeTime(time)).elon
  } catch (error) {
    console.warn('计算太阳位置失败,回退到简单公式:', error)
    // 使用简单近似作为后备
    const yearStart = new Date(time.getFullYear(), 0, 1)
    const dayOfYear = Math.floor((time.getTime() - yearStart.getTime()) / 86_400_000)
    return (dayOfYear * 360 / 365.25 + 280) % 360
  }
}

📈 性能优化

1. computed 派生代替 watch

组件内一律 computed(() => transform(timeRef.value)),依赖追踪自动化,无需手动 watch + 缓存变量:

typescript
const timeRef = computed(() => unref(props.time) ?? new Date())
const sunLon = computed(() => sunLongitude(timeRef.value))

2. Composable 层聚合

useSevenLuminaries.ts 把太阳/月亮/五星一次算完,多个环共享同一个 computed 结果,避免同一时刻反复调用 astronomy-engine。

🔗 相关组件与工具

圆环 / 圆心

基础与控制

  • PolarCanvas:提供极坐标系统基础
  • CompassSidebar:左侧嵌入式 Sidebar(时间/视口/View 专属工具位)
  • DegreeScale:显示度数刻度
  • tyme4ts:中华传统历法计算(与 astronomy-engine 配合)

Composable / 工具

📖 更多资源

🎯 最佳实践

  1. 在 utils 层集中调用 astronomy-engine —— 组件层只消费纯函数结果
  2. 一律 try-catch + 后备近似 —— 避免极端时间导致渲染中断
  3. computed 派生代替 watch —— 依赖追踪自动化,保持响应式链完整
  4. 通过 Composable 复用计算 —— 同一时刻多环共享一次天文计算
  5. 结合 CompassSidebar —— 让用户拖时间条即时看到天体变化

这个库在乙巳观中发挥了关键作用,为七曜入宿天象盘、回归年闰月盘、观斗盘、苏州石刻天文图等罗盘提供了精确的天文计算基础。

道由天观 · 静观其变