用 Canvas 画一个会呼吸的粒子世界
从一个点到一片星网,理解动画循环、距离检测与交互反馈的基本原理。
·3 分钟阅读· 示例文章
示例文章:介绍本站粒子实验使用的基本原理,不是个人经历或性能研究报告。
从一个粒子开始
粒子不是某种复杂对象。最小实现只需要位置、速度与半径。每一帧更新位置,再把圆点画到画布上,就能让它动起来。
interface Particle {
x: number;
y: number;
vx: number;
vy: number;
}
function advance(particle: Particle, delta: number) {
particle.x += particle.vx * delta;
particle.y += particle.vy * delta;
}
这里的 delta 是经过限制的时间步长,用于降低不同屏幕刷新率造成的速度差异。切回后台标签页时,也要防止一次累积过大的时间间隔。
两个点,什么时候连线
计算两个点的平方距离,与连线半径的平方比较即可。只有足够近的粒子才画线,距离越远,线条透明度越低。
const dx = a.x - b.x;
const dy = a.y - b.y;
const distanceSquared = dx * dx + dy * dy;
const connected = distanceSquared < connectionRadius ** 2;
最直接的算法会比较每一对粒子,复杂度是 O(n²)。对于数量受限的小实验,它足够清楚;如果需要成千上万的粒子,再考虑空间网格或其他邻域查询结构。
把指针变成引力源
指针附近的粒子可以产生轻微偏移,为画面提供可感知的反馈。移动端则应保留正常的页面滚动,而不是让整个画布截获所有手势。
交互反馈应当克制:过强的吸引力会让粒子迅速聚成一团,过强的排斥力则会把画面清空。
动画之外的体验
一个完整实验还需要暂停按钮、可理解的参数名称,以及减少动画偏好的支持。用户选择减少动画时,默认显示静态帧,并让他们主动决定是否开始播放。
当画布离开视口或页面进入后台时暂停绘制,可以节省不必要的计算。设备像素比也应设置上限,避免高分屏上的绘制成本过高。
亲手试一试
打开交互式粒子场,改变粒子数量和连线距离。观察哪一种参数组合让结构清晰,哪一种会让画面变得拥挤。视觉参数没有唯一正确答案,实际试验比猜测更有帮助。