Astra 星域 — 滚动聚拢与散开效果复刻

向下滚动 · 拖拽旋转 · 移动鼠标扰动
关于这个复刻

星星先聚成一个「6」,滚动时散作星海。

整个画面是一层全屏正交相机下的 GPU 粒子场。约 5000 颗星星被分配到 5 条曲线上—— 这 5 条曲线由构成数字「6」的 5 段 SVG 描边路径生成,并各自带一条正弦形的 Z 向起伏, 所以正面看是一个数字,稍微一转就散成有厚度的银河。

滚动条并不移动这些粒子,它只是把一个 0 → 1 的进度送进顶点着色器。 位置在「沿曲线」和「随机星域」两个目标之间插值,星星的亮度、尺寸包络、闪烁速度、 视差漂移全部随同一个进度衰减。

运行细节
  • 粒子数5 条曲线 × (220 / 170) × 密度 4,另加 12% 常驻背景星与中心星团
  • 着色器顶点端完成聚拢/散开/形变/透镜/动量,片元端画星芒与核心
  • 鼠标128×N 的 ping-pong 浮点纹理保存每颗星的位移与速度,指数阻尼滑行归位
  • 拖拽五层各带不同的跟随延迟(lag 0.18 → 0.86),转起来有视差
  • 后期UnrealBloom(阈值 0.08 / 半径 0.72)+ ACES 色调映射
形状 · openai-knot
形状 cue

路过时,星海重新排列。

页面里的每个「形状锚点」都是一段隐藏的 SVG。当它靠近视口中心时,脚本用 getPointAtLength 沿全部子路径等弧长采样 1024 个点,写进一张 1024×1 的 RGBA 浮点纹理:xy 是归一化坐标,zw 是这颗星 所属子路径的起止区间。

顶点着色器据此为每颗星挑一个落点:先按种子取到所属子路径,再在该子路径内部按 密度衰减分布,加上法线方向的散布和轮廓深度。于是星星不是「贴」到轮廓上,而是 像一条有厚度的星流缠在图形上,还能整体绕 X/Y 轴慢慢转。

形状 · cursor
交互

鼠标推得动星星。

指针不是靠 CPU 逐颗算的。每颗星在一张 128×N 的半浮点纹理里占一个像素,存 (位移xy, 速度zw)。每帧把指针这一小段移动当成一条线段,离线段越近的星 受到的冲量越大;随后所有星按 drag = 2.3 / √mass 的指数阻尼自己滑回去, 大星重、小星轻,散开的节奏就自然分层。

按住拖拽则是另一路:五层曲线各有不同的跟随时间常数,松手后以更慢的弹性回正。 键盘方向键同样可用,按 R 重播开场动画。

扩展

加一个图案,只需要加一段 SVG。

形状不是写死在代码里的。页面上任何带 data-astra-shape 的元素, 只要里面有一个带 viewBox<svg>,脚本就会在它靠近视口中心时 沿它所有 <path> 的描边等弧长采样 1024 个点,把星星吸过去。 没有构建步骤,也不用改一行 JS。

下面这个是按同样的原理加的第四个图案:11 条等分射线组成的星芒。 它是用代码算出来的——每条射线就是一段 M x1 y1 L x2 y2, 沿曲线的密度衰减会让星星在射线中段聚集、往两头变稀,于是看起来像真的在发光。

形状 · claude-burst