打开网易新闻 查看精彩图片

一个坐标系错位,能让4次重构全部白干。

frandy.dev的时间轴动画最近卡在一个诡异bug上:霓虹光带穿过三条轨道,本该在节点圆点处精准闪烁,实际效果却像喝醉了酒——有时提前,有时滞后,偏移量还随滚动位置和卡片状态随机变化。

开发者Frandy花了整整一天,最终发现这不是逻辑错误,是建筑级失误。就像用北京时间的表去对纽约的航班,两个系统各自正确,凑在一起就乱了套。

光带在"眼前",节点在"纸上"

光带在"眼前",节点在"纸上"

问题的根源藏在两个看不见的坐标空间里。

traveling light(行进光带)活在viewport空间——以可见覆盖层的左边缘为原点,按像素计算位置。你屏幕上能看到多少,它就认多少。

节点位置却按card space(卡片空间)计算——从整个轨道的最左端开始累加像素宽度,包括那些已经被滚出屏幕、你看不见的卡片。

这两个数值只在一种情况下相等:滚动位置为0,且所有卡片完全展开。任何偏离——往右滑一下、折叠一张卡片——它们就开始分道扬镳。

Frandy的前4次重写都在优化数学公式,试图用更精密的计算弥合裂缝。但裂缝的本质是地基错位,粉刷墙壁没用。

第5次尝试:停止计算,开始测量

第5次尝试:停止计算,开始测量

解决方案粗暴得让人尴尬——直接问浏览器。

getBoundingClientRect()这个方法,返回的是元素相对于视口的实际渲染位置。不是理论值,不是计算值,是浏览器已经画在屏幕上的那个真实坐标。

Frandy把节点测量逻辑改成这样:每次需要位置时,直接取DOM节点的现场读数。滚动时重新测,卡片宽度变化时重新测,筛选条件改变时重新测,窗口缩放时重新测。

用一个dirty flag(脏标记)做节流,确保每帧动画最多测量一次。开销可控,精度拉满。

光带现在每次都在节点圆点处精准闪烁。不是因为数学更漂亮了,是因为数据源从"我以为"变成了"浏览器看到"。

同期更新的7个细节

同期更新的7个细节

这次提交还打包了一堆体验优化,值得逐条拆解:

主题系统:完整的光暗双模式,4种强调色可选。localStorage(本地存储)记忆用户选择,优先级高于管理后台的默认设置。桌面端用下拉菜单,移动端做成下滑面板,滚动时和"返回顶部"按钮互斥显示——避免两个浮层打架。

时间轴交互:橡皮筋拖拽效果、弹簧物理动画、首张卡片粘性定位、双击展开面板、卡片序号水印、呼吸式预览圆点。这套组合拳让横向滚动有了质感。

三轨道脉冲:彗星拖尾、速度变化、护送偏移、节点闪烁带旋转+涟漪扩散、未来卡片颜色回退、干净重启。光带不再是匀速滑动的装饰,有了叙事节奏。

UI打磨:芯片/标签栏边框修复、返回顶部按钮重新对齐、区块内边距和导航高度增加、文字不透明度优化。没有新功能,全是可见的舒服。

项目尚未发布。桌面端时间轴已完成,下一步是纯设计走查——给每个区块做移动端适配,然后接管理后台。冻结功能开发,先让现有内容看起来对味。

Frandy在文末留了个小功能预告:模板系统,用来快速回复FAQ或存代码片段。

那个让他重写4遍的坐标bug,最终教会一件事——当屏幕显示和数学推导持续打架,大概率是你选错了参考系。浏览器已经算好了答案,getBoundingClientRect()只是递过来一张纸。

你最近有没有遇到过"计算很对,效果很错"的类似场景?最后是怎么发现坐标系错位的?