返回资讯中心
外部精选
软件工程
#开发者实时流

Astronoby 项目用 Ruby 生成 SVG 星空图

来源标题:SVG sky map with Ruby and Astronoby

开发者展示了如何用开源天文库 Astronoby 结合 Ruby 生成指定日期、时间和地点的 SVG 星空图。文章从最基础的 400×400 像素 SVG 画布和单颗恒星入手,逐步讲解天空盘的绘制原理。Astronoby 虽未发布 v1.0,但作者认为其已足够成熟,可支持多种使用场景。

Hacker News 最新thunderbong2026/11/10 · 今天30 分钟阅读

以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。

你有没有想过,你出生那天的星空是什么样子?别光看,动手做一个,其实很简单!

虽然我对 Astronoby 在发布 v1.0 之前还有很多想法,但它现在已经足够成熟,能覆盖不少使用场景了。其中一个我一直想尝试的,就是为指定的日期、时间和地点生成一张 SVG 星图。

现在已经有很多网站提供自己的星图了,但和往常一样,我喜欢的是弄明白它到底怎么运作、自己能亲手做出来,更重要的是,给社区提供一个开源版本。

先从最简单的开始:不用 Ruby,不用动态数据,只画一张图,上面放第一颗星。我们的 SVG 放在一个 400px 的带边框正方形里:

<svg viewBox="0 0 400 400" width="400" height="400" style="border: #ff0000 solid 1px"

</svg>

viewBox 属性定义了 SVG 自己的坐标系,两个轴都是从 0 到 400。它和屏幕上的实际大小无关,所以 SVG 被缩放时,图形会跟着缩放,而不是被裁掉。

接下来是天空本身。我敢肯定你脑海中已经浮现出一个圆盘了,这正是我们需要的。不过还是花一分钟想想,为什么星图常常被画成一个圆盘。

如果你走到乡下,站到一片大田野里,身边没有什么太高的东西,你能看到前方地平线。身后也有。实际上四周都有。整条地平线是一个完美的 360° 圆圈,而你就在圆心。

然后你抬头看天顶。从地平线开始,你的视线划出一道弧线,一直延伸到天顶。如果地面是透明的,你还能看到正下方那个点,也就是天顶的对立面——天底。

整片天空是包围你的一个球体,但只有地平线以上的那一半可见。你 literally 就是你自己的宇宙的中心。

那么,怎么从一个半球变成二维表示呢?没有完美的投影,你总得在某些方面妥协:角度、距离或者面积。

既然地平线是一个圆,把天空表示成圆盘就很自然了。除此之外,选哪种投影是任意的。用球极投影可以保持角度和形状,用等距投影可以让从天顶出发的距离保持准确,还有其他各种投影。每种投影都有自己的取舍,没有普遍“正确”的那一种。我们这里用方位等距投影。

把天球半球画成一个漂亮的深色圆盘。SVG 里用 circle 元素,属性如下:

<svg viewBox="0 0 400 400" width="400" height="400" style="border: #ff0000 solid 1px"

<circle cx="200" cy="200" r="198.5" stroke="#3262a8" fill="#000000" stroke-width="3" /> </svg>

下一个例子里我会去掉边框,因为我们已经看过视口长什么样了。注意半径并不是 SVG 尺寸的一半,而是留了足够的空间让边框放得下。

第一颗星,我们用一颗简化的北极星(α Ursae Minoris),假设它正好在天球北极点上。

作为天极,它的坐标一整天、一整年都不会变。它的方位角(绕地平线的方向)是零。而它的高度角(高出地平线的角度)就是观测者的纬度。我住在巴黎,北纬 48.8575°,所以天极始终在地平线以上正好 48.8575° 的位置,位于南北轴上。

所以我们已经有了 cx = center_x = 200,还需要一个小计算,把高度角从度数换算成 cy:

cy = center_y - radius * (90 - altitude) / 90 cy = 200 - 198.5 * (90 - 48.8575) / 90 cy = 109.258

这里没有什么特别的数学,我们算的只是:基于 SVG 的大小和中心位置,这颗星应该画在离中心(天顶)多远的地方。

有了坐标,剩下的就是画星:

<svg viewBox="0 0 400 400" width="400" height="400"> <circle cx="200" cy="200" r="198.5" stroke="#3262a8" fill="#000000" stroke-width="3" /> <circle cx="200" cy="109.258" r="1" fill="#ffffff" /> </svg>

第二步:真实的星空

现在我们有了一块天空背景,也能在上面画星了,接下来需要支持的不只是高度角,还有方位角。

我们使用两个星座——大熊座和小熊座——主要恒星的真实坐标,观测地点是巴黎,时间是 2026 年 9 月 24 日 22:00 UTC(当地时间午夜)。这些数据你就先信我吧,不过别担心,文章后面我们也会讲怎么生成它们。

(altitude, azimuth)

Ursa Major

(20.769, 354.809) (15.410, 354.390) (14.187, 346.314) (18.277, 344.282) (19.297, 338.649) (20.346, 334.149) (17.429, 327.801)

Ursa Minor

(49.061, 0.897) (49.624, 354.867) (48.876, 347.805) (45.296, 342.678) (46.410, 339.003) (41.192, 336.391) (40.703, 340.566)

高度角的计算我们已经有了,但那其实是个简化公式,因为之前那颗假星正好在天极上。方位角在 SVG 里就是绕中心的角度,有了它我们就能根据高度角算出 cx 和 cy。这一次,免不了要用一点三角函数。

在三角圆上,方位角的正弦和余弦分别给出水平和垂直分量。然后我们还要用到高度角(我们把它叫做 distance,因为它实际上就是距离圆心的距离)以及中心的坐标。

distance = radius * (90 - altitude) / 90 horizontal = center_x - distance * sin(azimuth) vertical = center_y - distance * cos(azimuth)

注意我们用的是减号而不是加号,这是天文学惯例:东在左,西在右。和地图相比看起来是反的,但星图本来就是让你面朝南方、举在头顶看的。

方位角是从北开始顺时针测量的,这也解释了为什么水平方向的值用正弦函数。这个线性公式就是我们的方位等距投影:位于 45° 高度角的星,正好画在到边缘一半的位置。

(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →