首页 > 解决方案 > 如何让mousemove在每个特定时间运行一次

问题描述

我正在尝试用鼠标(游戏)进行 div 移动。这是一段 jQuery 代码:

var a = $('.player'); // the div i want it to move
var all = $('.container'); // this is full hight / width container (all the page)

$(all).mousemove(function (e) { // if the mouse move the div move

    $(a).animate({

        left: e.pageX

    },50)

});

它确实有效,但它有一个滞后,因为它在第二个中检测到近 100 个 pageX(或者我认为的)

所以我尝试每 0.5 秒移动一次以消除滞后:

var a = $('.player');// 我希望它移动的 div

var all = $('.container');// 这是完整的高度/宽度容器(所有页面)

$(all).mousemove(function (e) { // if the mouse move the div move

     setInterval(function(){

         $(a).animate({

             left: e.pageX       // move the div  once every 0.5 s

         },50);

    } , 500 );  

});

但它不起作用!

标签: jqueryfunctionsetintervalmousemoveonmousemove

解决方案


这是因为您的代码在每次鼠标移动时都会创建一个额外的新计时器间隔循环。那些会像疯了一样堆积起来!

我认为您真正想要的是去抖动限制您的mousemove事件,以便它们每 500 毫秒触发一次。我可以发誓jQuery 在它的库中有这个,但我找不到它,所以这里是你如何使用 vanilla JavaScript 来做的:

// Lodash has one of these; don't rewrite if you already have a debouncer loaded

function debounce(ms, fn) {
  let deferredCall = null;
  let timeout = null;
  return (...args) => {
    if (timeout) {
      // We're currently waiting before calling our function
      deferredCall = () => fn(...args);
    } else {
      // Run immediately
      fn(...args);

      // Don't run again until some time has passed
      timeout = setTimeout(() => {
        timeout = null;
        if (deferredCall) {
          // Call the latest deferred call
          deferredCall();
          deferredCall = null;
        }
      }, ms);
    }
  };
}

这个 debounce 函数创建了一个新版本的函数,所以你可以包装你的 mouseMove 函数并在你的事件处理程序中使用它:

$(all).mousemove(
  // move the div once every 0.5 s
  debounce(500, e => { 
    $(a).animate({
      left: e.pageX
    }, 50);
  })
);

推荐阅读