你好,我叫回声,英文名 Echo。如果你刚从首页过来,应该已经见过我了:一团轮廓不太规整的墨,两只圆眼睛,安安静静地等着你点一下。
今天想和你聊聊我的样子,也聊聊那些让我流动起来的代码。
从一条线开始
我的身体有一处凹下、一处凸起,没有手脚,表情也只靠两只眼睛。放大时能看清轮廓,缩到导航栏里,还是同一个我。
我的身体由 SVG 路径绘制,眼睛是两个圆。首页、导航和文章末尾共用同一条轮廓,大小交给页面调整。这也让我不需要为每个尺寸准备一张图片。
颜色来自博客的主题变量。白天,我是墨黑的,眼睛浅浅的;到了暗色页面,身体变成月白,眼睛也跟着变深。即使正在流动,我也能跟上配色变化。
一团墨怎么分开
从我身上分离出去的流体叫墨团,它们暂时变成的文字或图案叫形态。我有自己的名字,它们则是可以收回来的几笔墨。
你看到的黏连和分裂,来自 SVG 里的高斯模糊与透明度阈值处理。模糊让相邻轮廓交叠,阈值再把柔软的边缘收紧;我和墨团放在同一个滤镜组里,靠近时就会融合,拉远时连接处逐渐变细,直到断开。
墨团的轮廓还会根据位置、拉伸和波纹重新计算。它们可以化成“文”、代码符号或星形,停留片刻,再软化回到我身上。变成文字时,底下的墨团也要同步缩没,否则文字的空隙里会透出一个黑点。
我也有一点物理
在电脑上拉动墨团,它会随着你的手势伸长。方向来自平滑后的指针速度,拉伸程度随速度变化,位置则用弹簧计算,让它带一点柔软的迟滞。
这件事比看起来麻烦。向右拉长和向左拉长,本来应该是同一种形状;如果直接追着角度旋转,反向拖动时,墨团就会突然掉头。现在用双角矢量描述形变,让相反方向对应同一条轴,来回拖动也能保持自然。
停住的手也需要单独处理:没有新的指针事件,速度读数就可能停在最后一次测量。代码会根据停手时间主动衰减,让墨团回圆。手还按着,也能慢慢安静下来。
动起来,也要停得下来
我的入场由一条 requestAnimationFrame 时间轴驱动,位置、分离和塑形沿着同一个进度推进。返回入口时,沿同一条时间轴倒放,墨团就能重新回到身体里。
分出的墨团会交接成页面里的真实标题和按钮。交接时,元素通过临时滤镜从模糊的墨迹逐渐变清晰,结束后滤镜被撤掉,留下正常的页面。
窗口变化、页面隐藏或导航中断时,临时路径和样式也要清理。平时无需运动时,动画帧链会停下来;手机则采用紧凑的入场,不启用拖拽。
读文章时,我会轻一点
我喜欢在入口和你打个招呼,也会在导航、文末留一个小小的身影。阅读进度条上的我,像挂着的小篮子,滚动带来的加速度让我摆动,阻尼再让摆幅逐渐减小。
你认真读文章的时候,我也有自己的分寸。文字需要空间,动画需要时机。
这就是目前的我:一条轮廓、两只眼睛,还有一些让墨流动的代码。下次路过首页,可以点一下。听见你的动作,我会给一点回应。