模式 · 28
邻近场
Proximity field · proximity-field一个指针位置,驱动附近一整片元素的响应。
只让被指中的元素响应,会把画面切成“命中/没命中”两档。邻近场给每个点算同一个距离权重,再用它控制大小或推开距离;移动时各点连续变化。离指针正中的点方向不确定,要给它一个稳定的兜底方向。
公式
dᵢ = hypot(xᵢ − pointerX, yᵢ − pointerY) wᵢ = max(0, 1 − dᵢ / radius)^exponent positionᵢ += unit(radialVector) × push × wᵢ
参数
| 本页默认 | 成熟实现 | |
|---|---|---|
| radius | 130 px | —影响区域的半径。 |
| exponent | 2 | —增大它,中心更尖、边缘更快衰减。 |
| mode | scale / push / both | — |
怎样做好
- 用同一个距离函数算全部元素,再把结果映射到大小、位移等多个通道。www-motion/rewrite/lib/motion-kit.js:176–187
- 径向向量长度为零时给固定方向;直接除以距离会得到无效坐标。www-motion/rewrite/lib/motion-kit.js:179–185
- 位置与强度分开算,再对显示值阻尼跟随,能保留指针移动的连续感。www-motion/rewrite/lib/motion-kit.js:176–187
在我们的案例里
邻近场出现在 22 个案例,径向衰减出现在 19 个;两者合计覆盖 23 个不同案例。moments 的引力空洞就是用二次衰减,把附近元素沿径向推开。
出现在 23 个案例
参考实现 · basics.js
/** Influence of one pointer on many elements; returns 0..1 per element. */
export const field = (points, px, py, radius, exponent = 2) =>
points.map(p => radialFalloff(Math.hypot(p.x - px, p.y - py), radius, exponent));
/** Influence of a point at distance d from a source of radius R: 1 at the centre, 0 at R. */
export const radialFalloff = (d, radius, exponent = 2) => (d >= radius ? 0 : (1 - d / radius) ** exponent);