必须用 wheel 事件监听向下滚动,因其更底层及时且可区分方向;scroll 事件延迟高,不适合实时提示;需用 preventdefault() 和 passive: false,并用 transform/opacity+will-change 优化动画,配合 raf 节流与状态锁防重复触发。

滚动事件监听必须用 wheel,不是 scroll
很多人一上来就给 window 绑 scroll 事件,但鼠标滚轮触发的是 wheel 事件——它更底层、更及时,且能区分方向。而 scroll 是滚动结束后的被动响应,延迟高,还可能被防抖/节流干扰,完全不适合做“向下滚动时立刻提示”的交互。
关键点:
-
wheel事件的deltaY大于 0 表示向下滚动(注意:不是所有设备都一致,但主流浏览器和触控板默认如此) - 必须用
preventDefault()阻止默认滚动行为,否则动画会和页面滚动打架;但只在需要干预时调用,避免影响可访问性 - 推荐用
passive: false显式声明监听器非 passive,否则 Chrome 会静默忽略preventDefault()
element.addEventListener('wheel', (e) => {
if (e.deltaY > 0) {
showHint(); // 触发你的提示动画
}
}, { passive: false });
提示动画推荐用 transform + opacity 配合 will-change
CSS 动画卡顿?大概率是用了 top/left 或重排属性。向下滚动提示通常出现在视口底部附近,应优先走合成层:
- 用
transform: translateY()替代top,避免 layout - 用
opacity控制显隐,GPU 加速友好 - 加
will-change: transform, opacity提前告知浏览器优化(仅对频繁触发的提示元素加,别滥用) - 动画时长控制在 200–300ms,过长显得迟钝,过短用户来不及感知
.hint {
opacity: 0;
transform: translateY(10px);
transition: opacity 250ms ease, transform 250ms ease;
will-change: transform, opacity;
}
.hint.show {
opacity: 1;
transform: translateY(0);
}
避免连续触发导致动画叠加或卡死
鼠标滚轮一次滚动可能触发 5–20 次 wheel 事件,如果每次都在执行动画逻辑,showHint() 可能反复调用,造成 class 切换冲突、动画重入、甚至内存泄漏。
- 用
requestAnimationFrame节流:确保同一帧只处理一次 - 加状态锁:比如
isHintVisible,防止重复显示 - 动画结束后手动移除
.show类,或用animationend事件清理 - 不依赖 CSS
animation的无限循环,改用 JS 控制单次播放
let isAnimating = false;
function showHint() {
if (isAnimating) return;
isAnimating = true;
hintElement.classList.add('show');
hintElement.addEventListener('transitionend', () => {
isAnimating = false;
}, { once: true });
}
移动端 Safari 的 wheel 兼容性要单独处理
iOS Safari 不支持 wheel 事件(直到 iOS 16.4 才部分支持,且需用户开启“辅助功能 > 触控 > 滚动”),绝大多数 iPhone/iPad 用户实际触发的是 touchmove + 惯性滚动,但无法直接读取滚动方向。
- 检测是否为 iOS:用
navigator.userAgent.includes('iPhone') || navigator.userAgent.includes('iPad') - 降级方案:监听
scroll事件,对比scrollY前后值判断方向(注意首次加载时的初始值) - 更稳妥的做法:只在桌面端启用 wheel 提示,移动端用固定位置的常驻小提示(如右下角“下滑查看更多”)
- 不要试图用
pointermove模拟,方向判断不准,且和原生滚动冲突严重
真正难的不是写动画,而是让提示只在用户**明确向下滚动意图时出现一次**,且不干扰后续操作——这需要结合事件粒度、渲染时机和平台特性反复调。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











