数值 · 04
钳制与区间映射
Clamp and map · clamp-map把输入从一个区间换算到另一个区间,并决定能否越界。
滚动进度、指针距离和透明度往往使用不同单位。先归一化再插值,比到处散落比例常量容易核对。是否钳制必须明确:透明度通常要停在 0…1,拖拽位移则可能故意越界。
公式
t = (x−a)/(b−a) y = c + (d−c)·t clamped: t ← clamp(t, 0, 1)
参数
| 本页默认 | 成熟实现 | |
|---|---|---|
| input range | 0…1; subrange .3… .6 | GSAP normalize, mapRange局部区间把一段滚动映射成完整的 0→1。 |
| clamped | true by default | GSAP mapRange is unclamped库的默认值不同,调用时写清楚意图。 |
怎样做好
- 把输入段与输出段同时写出,别把
.3和.6藏在多处条件判断里。GSAP src/gsap-core.js:555,574–578 - 映射透明度前钳制;GSAP 的
mapRange本身不钳制,越界值会继续外推。GSAP src/gsap-core.js:574–578 - 只在需要外推的交互里关闭钳制,并在显示层处理超出可见轨道的结果。
在我们的案例里
64 个案例涉及钳制或区间映射,是这组值函数里最常见的。picasso-ecommerce 将滚轮增量写入目标进度时立即钳在 0…1;这让场景在滚动边界保持稳定。
出现在 64 个案例
01Momentum Slider02Drag Gallery03Formation04Cardwall05Riffle07Rotunda09Lens Bloom10Frieze11Aperture12Folio13Cinema Reel14Stream Showcase15Hardback16Picasso Ecommerce17Assembly18Fathom19Emulsion20Portfolio Photographer
+46 更多
21Reverie22Boutique23Nova24Alive25Shape Trail26Membrane27Liquid Type28Filament29Pixels30Cipher32Cutout33Crema34Aster35Spring37Amour38Fluid Gallery39Marathon40Atelier41Desk 9542Isle44Atlas45Aurora46Rooster Rush47Overworld48Moments49Burst50Dimension51Morph52Meow53Relay54Lumen55Serene56Fleur57Atrium58Skyward59Helix60Crate61Prism62Flashlight63Viewfinder64Sand65Arrange66Tunnel67Reel68Type69Loupe
参考实现 · basics.js
export const clamp = (x, lo = 0, hi = 1) => Math.min(hi, Math.max(lo, x));
export const lerp = (a, b, t) => a + (b - a) * t;
/** Where x sits between a and b, as 0..1 (unclamped). */
export const normalize = (x, a, b) => (a === b ? 0 : (x - a) / (b - a));
/** Map x from [a, b] to [c, d]. Clamped by default, because overshooting inputs are the usual bug. */
export const mapRange = (x, a, b, c, d, clamped = true) => {
const t = normalize(x, a, b);
return lerp(c, d, clamped ? clamp(t) : t);
};