太阳钟
文章摘要
Sun Clock(sunclock.net)是一个纯前端的小网站,作者在 HN 上的账号是 perilunar。它是一个24 小时制的表盘,在盘面上直接画出太阳当前的位置,并根据你所在位置标出日出、太阳正午(solar noon)、日落、黄金时刻(golden hour)和各阶段暮光(twilight)的时间;同时还显示月亮的位置和月相,以及月升月落时间。除了时钟主视图,站点还有一个「Sun Calendar」年度日历视图。
作者在 About 里给出的工程指标很克制:页面重量约 100 KB,没有广告也没有追踪(只有一个来自 Simple Analytics 的极小统计脚本),需要 JavaScript 才能运行。隐私说明写得很直接:只收集聚合的用户统计;你的位置和设置存在浏览器本地,不会发到服务器;不保存也不发送 cookie。项目使用免费,不含广告,2026 年 6 月 26 日给代码加上了 MIT 许可。太阳和月亮的天文计算基于 SunCalc 这个 JS 库。
站点最有意思的一节是关于旋转方向的说明,也是作者花了篇幅解释的设计决策。在北半球,太阳在天空中的移动是顺时针方向的——作者顺带补了个词源:在钟表出现之前,顺时针叫 “sunwise”(随日),逆时针叫 “widdershins”,意思是「逆着走的方向」。但在南半球,太阳的移动是逆时针的,所以 Sun Clock 会根据你的纬度自动设定旋转方向:如果你在南半球,时钟就会「倒着走」(当然设置里可以改回来)。作者的理念是:理想状态下,无论你在哪个半球,时钟都应该和太阳同向转动;如果你面朝南,设成顺时针,面朝北则设逆时针,你要的是让盘面上的日出落在东侧。他还留了一个彩蛋式的提示:如果你朝对的方向、把屏幕倾斜到对的角度,时针会真的跟着太阳在天空中的运动走——具体怎么做「留作读者的练习」,但你要让屏幕落在黄道面内,并让太阳正午朝「上」。
使用提示部分说明:点击或悬停在各个色块上可以看到它们的起止时间,月亮、时针和中心圆点也都可以点/悬停。
更新日志本身也是一份小型产品史:2023-10-20 变成 PWA(可以装到设备主屏并离线使用);2024-02-13 加入年度日历;2024-05-23 加了在盘面上显示奇数刻度的选项,并让「使用 12 小时制」选项也应用到盘面数字;2026-01-01 修掉了新版 Safari 上月亮图标显示错误的 bug;2026-03-12 加了「秒针跳动」选项(默认仍是扫秒);2026-06-26 加上 MIT 许可。
HN 评论精华
这条帖子拿到 288 分、93 个节点。这类交互式小站的讨论有个典型走向:正文本来就少,而评论区变成了一场「我也做了一个」的大集市——至少十几位读者贴出了自己写的太阳钟/日照可视化项目。真正有信息量的部分来自两处:作者 perilunar 亲自下场回答边缘情况,以及 SunCalc 库的作者也现身了。另外还有两条意外有趣的支线:对「不肯交出定位」的普遍抗拒,以及一场关于「你脑子里的一年是顺时针还是逆时针」的自发民意调查。
- mourner 是全场最有价值的现身:他是 SunCalc 的作者,也就是这个应用背后做太阳计算的那个 JS 库。他很高兴看到这么漂亮的应用,并提醒作者他最近发布了一次大改版,精度提升很多。被问到参考资料时他讲了库的来历:大约 15 年前这是他人生第一个开源库,最初基于 Astronomy Answers 的文章(那些页面至今还在线),而 v2.0 是专门按 Jean Meeus 的《Astronomical Algorithms》一书的方法重写的。perilunar 回复说会去看新版本并更新。这条底下还聚了一小群 SunCalc 用户:xd1936 说他昨天刚用 SunCalc 给自己的 PebbleOS NOAA 雷达表盘加上了日出日落和黄金时刻,「每次有这类需求我第一个想到的就是它」;prometheus76 说他在做一个按罗马帝国方式计时的时钟应用——每天有十二个小时,从日出开始到日落结束,所以每小时的时长每天都在微微变化,这个库对他极其有用。
- staplung 提了唯一一组真正的技术边缘情况,也钓出了作者最实在的回答:他自己写过这类时钟但没决定好怎么处理「太阳升起但不落下」(以及反之)的情形;另外还要决定是显示今天的日出时间,还是一旦过了那个时间就切换成明天的——不管怎么选,UI 在某个时点都会跳一下,在中纬度差别很小但在高纬度和特定季节效果会相当剧烈。perilunar 逐条回答:实际上不成问题——你会在太阳午夜和日出/日落之间得到一条细细的暮光条,文字信息里则显示「Sunset: Does not occur」,而这种情况下日出/日落的扇区本来就很宽;时间选择上他决定在午夜重算;UI 跳动通常不剧烈,每天只是几分钟和零点几度,最大的一次跳变发生在夏令时切换时——盘面会整体旋转 15 度,「大多数人那时候在睡觉,但看它跳一下挺酷的」。
- TimTheTinker 提了一条具体的改进建议:看起来「黄金时刻」被硬编码成了日落前一小时,建议改为基于太阳在天空中的高度角。在高北纬和低南纬地区,太阳可能随季节在地平线附近停留很长时间——比如冰岛春秋两季的部分时期,黄金时刻能持续一天中的大部分时间,对摄影和纯粹欣赏景色都极好。mordechai9000 补了个更极端的例子:在阿拉斯加北部,冬天它能持续一天中大部分时间,夏天则是一夜中大部分时间。
- 最强的一致需求是手动设置位置。dvh 的「让我手动选位置」是最高票的功能请求之一,edelind 说浏览器定位有时偏得厉害,没有手动设置对他就没用,monegator 明确拒绝交出自己的位置。divbzero 和 perilunar 都指出其实可以做到——齿轮图标打开设置面板后能设经纬度。Retr0id 提出了一个更根本的诉求:他希望浏览器默认就支持这件事——不是「允许这个站点知道你的位置吗?」而是「选择一个位置提供给这个站点」,「我确信有扩展和开发者选项能做到,但我想要的是这成为默认」。GJim 更直白:「我当然不会把我精确的 GNSS 坐标给任何随口就要的家伙。老实说我很惊讶有人真的会给。」不过 globular-toast 和 cerebrum01 把这个需求转成了一个正面功能:能在地图上设一个点、拖动它并实时看时钟变化会更酷,而且「想知道太阳在别处会怎么走的人也用得上」。
- rhema 贴了自己在 p5.js 里做的版本,把「太阳正午」放在盘面顶部,并抛出一个让好几个人接住的问题:你以为中午 12 点是真正的「正午」/太阳正午?除非你正好住在时区中心,否则不是。 divbzero 补充「而且你还得不实行夏令时」;reaperducer 又加了一层——美国西部有些地方整个镇按自己的时间运作,「唯一能找到『正确』时钟的地方是邮局,连市政厅都不是」;GolfPopper 从天文角度补全:「地方正午」的客观时间还会因为地球轨道不是完美圆形、以及地轴相对轨道面的倾斜而变化,这个偏差由时差方程(equation of time)描述。dilap 因此提出希望能把「真正午」而不是 12 点放在盘面顶部。
- vesinisa 引出了整帖最出人意料的一支:他注意到作者的年度日历把一年画成顺时针(一月在 12 点到 1 点,二月在 1 点到 2 点,十二月在 11 点到 12 点),而他最近在一群好友里做了个小调查,发现超过 80%(包括他自己)一直把一年想象成逆时针旋转的(一月在 12 点到 11 点,二月在 10 点到 11 点,十二月在 1 点到 12 点)。「诡异的是我们没有一个人能解释为什么会有这种奇怪的逆时针心理图像,但所有这么想的人都说,记事起就一直如此。」
- 这条底下的自陈五花八门。layer8 说他脑子里根本没有一年的环形图像,更像一条连续的线——夏天亮、冬天暗——去年不和明年重合;一周、一个月也是如此,一天更不是(一天要转两圈),「有人会把一天想成两个圆吗?大概没有」。fwipsy 说他把一年想成顺时针但夏天在顶部、新年在 6 点位,因为对他来说春天「上升」、秋天(fall)「下降」更合理——他猜这个约定在南半球更好用;perilunar 回应说他也一样,而他就在南半球,所以夏天本来就在顶部。pineaux 的模型最复杂:一年就是个时钟,十二月在 12 点;但一天没有心里的时钟,恰恰因为他觉得钟面形状不适合表示时间——凌晨 3 点和下午 3 点感觉完全不同,所以他脑中是一个略有偏移、绕回自身的 3D 螺旋,像从上往下看两个半透明的钟面,下面那个稍微偏左,每个数字往上升一点,过了午夜 12 点数字迅速降回早上 6 点。Ostrogoth 的一年是逆时针的不对称椭圆,而且每个月都有对应颜色(十二月海军蓝、一月栗棕、二月冰蓝、三月正栗色、八月金色或麦黄),「从童年起就是这个图像」。cogogo 说这是他第一次这样想这个问题,觉得时钟表示挺好,但一年是他唯一能不加思索就有良好三维心理模型的东西——「现在我们大约走到秋分的 11/12 处,你可以想象地球倾斜的轴几乎垂直于射来的阳光」。
- vesinisa 和 perilunar 最后一起把这件事推到了原理层面。perilunar 指出从北极上方俯视时行星确实是逆时针绕太阳公转,大多数示意图也这么画,也许那就是这种心理图像的来源,并说他应该把它加成一个选项(连同一年从盘面顶部还是底部开始)。vesinisa 顺着做了个漂亮的对称论证:既然几乎所有地图都把北朝上,把地球画成逆时针绕日就说得通;这有点像日间的时钟顺时针转,大概是因为它对应北半球日晷的转向,而南半球的日晷是逆时针的。但他随即指出正反两面都能论证:如果我们真的从外部想象地球在空间中自转,以北为上时它自转也是逆时针的——那日间时钟是不是也该「倒着走」?而远方恒星构成的「固定」背景,对北半球观察者来说全年是顺时针旋转的,所以把一年画成顺时针一样正确。「一切似乎都取决于选择的视角。」
- Apple Watch 是另一条小争议线。Razengan 骂 Apple 不允许自定义表盘,「总是残缺的操作系统限制着他们了不起的硬件的潜力」。el_benhameen 和 animal_spirits 指出内置的「Solar Dial」表盘基本就做到了这个站点做的事,后者说它已经是自己的默认表盘;altairprime 反驳说「功能等价,但美学绝对不等价」,并在另一处说缺少一个简单的单指针表盘正是他对 Apple Watch 拒绝允许公开的第三方表盘设计最大的不满——他还贴了一个 2011 年就上线的实体单指针钟表变体。acidburnNSA 想要它出现在 Pebble Time 2 上,dveeden2 想要 Garmin 版并贴了目前找到最接近的一个应用。miniBill 想用彩色墨水屏加一个标准的 24 小时钟机构把它做成实物,guest__user 起哄「去做吧,开个 GitHub 加个购物车链接」。
- 「我也做了一个」的清单本身就是这条帖子的主要产出:mannanj 的 sunsignal.app(支持输入邮编,他在验证一个假设:把生活——包括午睡——安排在围绕太阳的节奏上会让人表现更好);jasonincanada 几天前做的一个 24 小时钟,但用12 进制、每分钟 72 秒(为了复用外圈的 24 小时刻度,再做 3 等分让「秒」接近正常秒);momentmaker 的 Sun Path(追踪太阳路径跨世纪的极缓慢偏移,含所有的分点和至点,他还当场修掉了 sheept 报告的触屏拖动地球失效问题——缺
touch-action: none);Arshwaraich 的 Sun Timezone iOS 应用;svennidal 的 solarclock(他人在冰岛,因为冰岛官方时间比太阳时早近一个半小时,他就把自己的钟当主时钟用了,位置直接硬编码所以一直没分享);Willingham 的 daylight-globe;franze 的 daylight.franzai.com(带整年概览滑块);charliewallace 的 dayspiral.com(把日出日落塞进更易读的 12 小时盘面);donohoe 的天气 web app(外环是未来 12 小时的天气、内环是昼夜转换,Arodex 吐槽「终于有人想到用开尔文给环境温度了」,作者回「我只是给人民想要的东西」);decoding 的 sunangle(他一直没能把计算结果和别的来源对照验证,正好可以拿 SunCalc 比);fer 推荐的 WeatherSpark(能按年降雨、云量、湿闷程度比较不同城市,他每次度假或搬迁前都查);bpev 在用的 sundial.page;以及 didymospl 表示自己还是更喜欢 timeanddate.com 那种更硬核的表格。 - zamadatix 提出的两个功能请求钓出了一段真诚的回复:他希望能在地图上点选多个点看与本地的差异,以及在日历视图里悬停某个时刻时用「着色」而非指针位置显示那一刻的状态。duman(另一个类似应用的开发者)说这几乎就是他做出来的东西:第一点他跳过地图改用搜索加保存城市,所有保存的地点都落在同一个 24 小时盘上,一眼就能看出与本地时间的差,好处是完全离线可用且在 Apple Watch 上也合适;第二点他只做对了一半——可以按 15 分钟增量移动盘面、昼光/暮光着色会随之变化,日历里也能跳到任意日期时间看每个城市的太阳状态,但那是按行显示而不是给时钟本身重新着色。「不过我更喜欢你的版本,悬停/擦洗一个时刻然后整个钟为那一刻重新着色,会合理得多。我要把它加进清单。」
- 另有几位提了同类需求:seanalltogether 和 sheept 都想要一条能在一年中前后滚动、看所有时间随之偏移的时间轴滑块——perilunar 回应说他在考虑把类似的东西加到日历页,或者单独加一个全年时间的「地毯图(carpet plot)」。karmakaze 反过来更想要常规 12 小时盘面加上下一次日出或日落,或者两个盘各管一个。SoulMan 希望盘面上能加上金星、木星这类可见行星。anshulsahni 想要移动端和桌面的小组件,yoyomo 想把它集成进 iPhone 的闹钟。
- 一个小趣味:wyclif 自称问个笨问题——绿色那根指针代表什么?perilunar 答:「绿色指针是分针。」而 Gecko4072(帖子提交者)贴出作者的 HN 账号链接,perilunar 回了句「hi :)」。tygon 的总结大概最能代表整体评价:这类动态 UI 缩放如今已是标准做法,但它让人愿意把这个页面挂在屏幕一侧,看着太阳落下去。