Back

文字星球

Published on 20th January 2025

Benjamin Robinet 有个网页作品令我印象深刻,它被发表在 X 上。

中国的网友可能无法查看,我私自将视频展示到下方,如有侵权请给我发邮件(Eamil: [email protected]),我会将其删除。

抛开醒目的大号文字不谈,位于屏幕中间的文字似乎在围绕鼠标排列,以弹簧动画驱动。

它是如何实现的?

solar-system

我们虚构一个星系,光标是恒星,它周围的单词是行星,值得注意的是,引力不适用该星系。离恒星越近,受到的斥力越大,到达某个距离后,斥力衰弱为 0。

around text

有了此认知模型,便可编写代码。

1. 向量

将星系看作一个平面直角坐标系,光标是原点,原点到元素的向量的模可以由下述公式计算:

v=x2+y2\|\vec{v}\|=\sqrt{x^2 + y^2}

如果你对该公式感到抽象,没关系,回忆一次勾股定理。

Pythagorean theorem
const c = Math.sqrt(a * a + b * b)

斜边 c 的长度等于向量 v 的模。

2. 元素的偏移量

设定从圆心开始,200 范围内的元素都遵循该原则发生偏移:离圆心越近,偏移量越大,达到 200 后衰减为 0,最大偏移距离为 100。

设光标为圆心,坐标为 px, py,元素的坐标为 ex, ey,则 dx = ex - px, dy = ey - py,向量的模 v = Math.sqrt(dx * dx + dy * dy)

则缩放比例为:

const scale = Math.max(0, 1 - v / 200)

发生偏移后,向量在 x, y 轴上的投影分别为:

const moveX = (dx / v) * scale * 100
const moveY = (dy / v) * scale * 100

计算在轴上的投影用到了向量归一化(英文:vector normalization),这是游戏里用来计算角色移动的方法之一,如果你对它陌生,请自行查阅相关资料,这超出了本文范围。

3. 性能优化

为了将动画尽可能的维持在 60fps,我做了不少工作,你可以在代码里查看 Word Galaxy,这可能不是最优解。值得一提的是,尽可能地避免密集使用 getBoundingClientRect,该 API 引发浏览器 reflow,可能会严重损耗性能。