You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何控制mousewheel事件触发间隔?视频滚动切换功能异常求助

问题排查与解决方案

看起来你遇到的核心问题是定时器堆积导致的锁机制失效,另外还有解锁时机不合理的问题,咱们一步步拆解:

问题根源分析

  1. 错误使用setInterval而非setTimeout
    每次触发滚轮事件时,你都会创建一个新的setInterval定时器——这个定时器会每2秒重复把animating设为false。如果短时间内触发多次滚轮(比如触控板快速滚动),就会同时存在多个定时器,它们会陆续把animating解锁,导致后续的滚轮事件又能触发,直接跳过多个视频。

  2. 解锁时机不匹配实际操作时长
    你的滚动动画只需要500ms,但你固定设置2秒后解锁,不仅没必要,还会在动画完成后留下很长的空白期,而如果这期间又有定时器触发,就会提前解锁。

  3. 未清除重复定时器
    没有对之前的定时器做清除操作,导致多个定时器同时运行,互相干扰animating的状态。

修复后的完整代码

let animating = false;
let timer = null; // 用来存储定时器ID,方便清除
let i = 1;

const goToNextVideo = function (callback) {
  if (i === 4) { // 总共4个视频
    callback(); // 即使不跳转,也要触发回调解锁
    return;
  }
  $('html, body').animate(
    { scrollTop: $(`.video-${i + 1}`).offset().top },
    500,
    function() {
      // 动画完成后执行操作
      $(`.video-${i + 1}`).get(0).play();
      $(`.video-${i}`).get(0).pause();
      i += 1;
      callback(); // 动画完成后解锁
    }
  );
};

const goToPreviousVideo = function (callback) {
  if (i === 1) {
    callback();
    return;
  }
  $('html, body').animate(
    { scrollTop: $(`.video-${i - 1}`).offset().top },
    500,
    function() {
      $(`.video-${i}`).get(0).pause();
      $(`.video-${i - 1}`).get(0).play();
      i -= 1;
      callback(); // 动画完成后解锁
    }
  );
};

// 绑定滚轮事件,用.on()代替.bind()(jQuery推荐写法)
$(window).on('mousewheel', function (event) {
  // 如果正在动画或视频正在播放,直接返回
  if (actuallyPlaying || animating) return;

  // 先清除之前的定时器,避免堆积
  if (timer) clearTimeout(timer);

  animating = true;
  const unlock = function() {
    animating = false;
    timer = null;
  };

  if (event.originalEvent.wheelDelta >= 0) {
    goToPreviousVideo(unlock);
  } else {
    goToNextVideo(unlock);
  }

  // 加一个保底的解锁机制,防止动画回调意外不触发
  timer = setTimeout(unlock, 1000);
});

关键改进点说明

  • setTimeout替代setInterval:我们只需要在操作完成后解锁一次,不需要重复执行,setTimeout更合适。
  • 动画回调触发解锁:滚动动画完成后才解锁,确保用户必须等当前切换完成才能触发下一次操作,完全贴合实际操作时长。
  • 清除重复定时器:每次触发事件时先清除之前的定时器,避免多个定时器同时修改animating状态。
  • 保底解锁机制:防止动画回调因为某些意外(比如元素不存在)没触发,导致永远锁死的情况。
  • 优化事件绑定:用jQuery推荐的.on()代替.bind(),兼容性和灵活性更好。

这样修改后,不管是鼠标滚轮还是触控板滚动,都能保证每次只能触发一次视频切换,不会出现连续跳的问题了!

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

火山引擎 最新活动