用requestAnimationFrame实现丝滑惯性滚动,核心是模拟物理速度衰减(如指数衰减0.97)+位置持续更新;松手时通过最近2~3帧位移差加权计算初速度(px/ms),rAF驱动更新scrollTop/scrollLeft,低于0.1px/ms时终止;需防布局抖动、处理边界回弹并清除句柄。

用 requestAnimationFrame 实现丝滑的物理惯性滚动,核心是模拟真实世界中的速度衰减(比如摩擦力)+ 位置持续更新,而不是靠固定时间间隔的硬编码步进。关键不在“帧率高”,而在“速度变化符合物理直觉”。
用 velocity + easing 模拟惯性衰减
用户松手瞬间记录当前滚动速度(单位:px/ms),之后每一帧按指数衰减(如乘以 0.95~0.98),再用该速度更新 scrollTop / scrollLeft。比线性递减更自然,也更接近 iOS/Android 的滚动回弹感。
- 速度采样建议用最后 2~3 帧的位移差加权平均,避免单帧抖动干扰
- 衰减系数选 0.97 左右较平衡:太小(0.9)停得太快,太大(0.995)拖尾过长
- 当速度绝对值低于 0.1 px/ms 时可直接终止动画,避免无限趋近于零
绑定 touch/mouse 事件获取初速度
在 touchend 或 mouseup 触发时,不能只取最后一次 touchmove 的位移——要结合时间戳算瞬时速度:
- 记录每次
touchmove的timeStamp和pageY(竖向)或pageX(横向) - 取最近两次 move 的 Δy / Δt 得出末速度,单位转为 px/ms(注意:timeStamp 是毫秒,pageY 是像素)
- 若只有一次 move(轻点),速度设为 0,不触发惯性
用 rAF 驱动平滑更新,不阻塞主线程
每次调用 requestAnimationFrame 时,根据当前速度计算新位置,再用 element.scrollTop = newValue 更新。不要用 setTimeout 或 setInterval 替代:
生成可在 deepbi 沙箱 iframe 内运行或作为独立文件运行的交互式 HTML 页面,使用 `window.deepbi` JS SDK 实现数据查询、空间管理、文件浏览及用户操作。当用户提出以下需求时启用该能力: - 创建 KPI 仪表盘、数据表格、文件浏览器、成员列表、管理页面; - 明确要求“转成 dhtml”、“转译成 HTML”、“把 XX 页面转成……”、“控制台页面”、“管理后台”、“DeepBI 页面迁移”; - 提及位于 `apps/console/src/featur
立即学习“前端免费学习笔记(深入)”;
- rAF 自动对齐屏幕刷新节奏(通常 60fps),且在页面不可见时暂停,省资源
- 更新前先用
getBoundingClientRect()或缓存当前 scroll 值,避免强制同步布局(layout thrashing) - 可配合
will-change: scroll-position提示浏览器优化渲染(仅对支持的浏览器生效)
处理边界与回弹(可选增强)
真实滚动常带边界吸附或轻微回弹。可在更新位置前加逻辑:
- 若即将超出容器范围(如 scrollTop maxScrollTop),将速度反向并衰减(模拟“撞墙反弹”)
- 超出后用 ease-out 缓慢拉回临界值,例如:目标位置 = 临界值 + (current - critical) × 0.3
- 回弹阶段仍走同一 rAF 循环,无需新开动画,保持控制统一
不复杂但容易忽略:务必在动画结束时清除 rAF 句柄,并重置事件监听状态;同时注意移动端需 preventDefault 在 touchmove 中禁用原生滚动,否则会和自定义逻辑冲突。


















