You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用wheel事件替代scroll事件实现导航栏对应区块的active状态高亮

问题原因

Locomotive Scroll这类平滑滚动类库会接管页面滚动逻辑,通过修改容器transform属性实现滚动效果,不会触发原生window的scroll事件,同时原生scrollY、offsetTop等属性获取的数值也和实际滚动位置不匹配,所以原有代码失效。

修复方案

直接使用Locomotive Scroll提供的内置滚动事件监听即可,不需要改用wheel事件实现。

第一步:绑定Locomotive Scroll的scroll事件

在你初始化Locomotive Scroll的代码后,绑定它自带的scroll事件,从回调参数中直接获取当前滚动位置等信息。

第二步:修正元素位置计算逻辑

因为Locomotive Scroll会给滚动容器添加transform位移,需要用getBoundingClientRect()配合滚动位置计算区块的实际相对位置,避免offsetTop的计算误差。

完整可运行代码
const sections = document.querySelectorAll("section");
const navLinks = document.querySelectorAll("nav a");

// 初始化Locomotive Scroll(和你原有初始化逻辑保持一致即可)
const scroll = new LocomotiveScroll({
  el: document.querySelector('[data-scroll-container]'),
  smooth: true
});

// 绑定Locomotive的内置滚动事件
scroll.on('scroll', (instance) => {
  let current = "";
  // instance.scroll.y就是当前的滚动距离,替代原生scrollY
  const scrollY = instance.scroll.y;

  sections.forEach(section => {
    const sectionTop = section.getBoundingClientRect().top + scrollY;
    const sectionHeight = section.clientHeight;
    if (scrollY >= sectionTop - sectionHeight / 3) {
      current = `#${section.getAttribute("id")}`;
    }
  });

  // 更新导航链接激活状态
  navLinks.forEach(each => {
    each.classList.remove("nav-active");
    if (each.getAttribute("href") === current) {
      each.classList.add("nav-active");
    }
  });
});
其他平滑滚动类库通用兼容思路

如果用的是其他类似的自定义滚动库,都可以套用这个逻辑:

  • 优先查找库官方提供的滚动监听事件,从回调参数中获取当前滚动距离
  • 元素位置计算统一用getBoundingClientRect() + 滚动距离的方式,避免offsetTop在transform位移场景下的计算误差
  • 不要用wheel事件实现,wheel事件只能监听鼠标滚轮操作,无法兼容拖拽滚动、键盘滚动、点击锚点跳转等滚动场景,会有大量边界问题

内容的提问来源于stack exchange,提问作者fay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 19:27:02