mouseMove非常迟钝

时间:2013-06-01 01:19:04

标签: javascript jquery html css

我正在尝试获取99designs将鼠标悬停在设计上时获得的图像效果。[99designs.ca] Logo design contest: Runningbug Needs Logo 220626

我目前正在鼠标移动中获取鼠标的位置,然后使用它移动我的popover <img>,一切正常,但它非常滞后...并且可能是它的来自如此多的电话。

获取鼠标的位置:

jQuery(document).ready(function(){
   //$("#special").click(function(e){
   $(".imgWrap").mousemove(function(e){
      //$('#status2').html(e.pageX +', '+ e.pageY);
      //alert(e.pageX + ', ' + e.pageY);
      mouseX = e.pageX;
      mouseY = e.pageY;
   }); 
})

我不确定我能做到的另一种方式......任何想法?

关于完整的事件过程如下:

  1. 用户将鼠标悬停在img标签上。
  2. 我按上述方法获得了鼠标的位置。
  3. <img>标记还调用js函数,该函数将img标记的位置更改为鼠标的位置。
  4. 实际上,您可以在此处查看:pokemonsite

    更新:我看到有一个赏金(谢谢!)。我现在有点忙,无法检查所有其他答案,但我会确保尽快检查

7 个答案:

答案 0 :(得分:2)

使用mousemove事件时,有几种方法可以提高性能。

  1. 在popover元素上使用backface-visibility: hidden来强制加速硬件。同样的事情可以通过transform: translate3d(0,0,0)获得,但这使得使用CSS transform函数变得困难(参见第2点)。

  2. 使用CSS transform函数进行绝对定位以避免重新绘制,但保持popover元素绝对定位或固定定位。

  3. 通过JS设置内联CSS时,请使用requestAnimationFrame以避免不必要的布局垃圾。

  4. (可选,可选)在悬停时隐藏光标,并使用popover元素作为位置指示符。

  5. 将所有可能的东西从JS移到CSS即。 :hover状态可用于切换popover元素的显示。

  6. 我制作了结合列出的所有内容的演示示例。光标位置和弹出窗口图像之间仍然存在一些延迟,原始问题中的示例链接都没有工作,所以我无法与之进行比较,但我希望有人认为这很有用。

    <强> DEMO

    <div id="imgHolder" class="imgHolder">
        <img src="//placehold.it/200x200" alt="" />
    </div>
    
    <div id="bigImgHolder" class="imgHover">
       <img src="//placehold.it/500x500" alt="" />
    </div>
    

    .imgHover { 
        display: none;
        backface-visibility: hidden;
        position: fixed;
        top: 0; left: 0;
        pointer-events: none;
    }
    
    .imgHolder:hover ~ .imgHover { display: block; }
    
    // uncomment if it makes sense
    //.imgHolder:hover { cursor: none; }
    

    var posX, posY;
    
    $('#imgHolder').mousemove(HoverImg);
    
    function HoverImg(e) {
        posX = e.pageX;
        posY = e.pageY;
        window.requestAnimationFrame(showBigImg);  
    }
    
    function showBigImg() {
        $('#bigImgHolder').css({'-webkit-transform': 'translateX(' + posX + 'px) translateY(' + posY + 'px)', 'transform': 'translateX(' + posX + 'px) translateY(' + posY + 'px)' });
    }
    

    的引用:

答案 1 :(得分:1)

如果绝对(x,y)位置不那么重要(意思是:在不破坏逻辑的情况下可以省略一些像素值),你可以尝试跳过mousemove-event的一些帧。

var globalSkipCounter = 0;
var globalSkipRate = 5;
$(".imgWrap").mousemove(function(e){
   if(globalSkipCounter >= globalSkipRate){
     var mouseX = e.pageX;
     var mouseY = e.pageY;
     do_stuff(mouseX, mouseY);
     globalSkipCounter = 0;
   }
   else{
     globalSkipCounter+=1;
   }
});

这样,您可以省略在每次mousemove事件上重绘图像,而只调用draw-routine(do_stuff),每5个事件一次。

答案 2 :(得分:1)

使用e.offsetXe.offsetY或(推荐)e.clientXe.clientY代替pageX和pageY。也许这将是一个更好的解决方案。注意:据我所知,offsetxoffsety在Firefox中不起作用。

答案 3 :(得分:1)

试试这个:

jQuery(document).ready(function(){
     $(".imgWrap").mousemove(function(e){
     e.stopPropagation();

     mouseX = e.pageX;
     mouseY = e.pageY;
    }); 
})

答案 4 :(得分:1)

缓存位置并将更新包装在if(oldpos !== newpos)类型检查中(记住更新其中的oldpos)。

使用requestAnimationFrame来处理更新 - 如果你有一个正常的函数并将其作为回调传递,那么每帧只调用一次(即不使用匿名函数)。

最后使用transform:translate(x,y)设置位置并更好地利用GPU等。与此相关,如果你想使用top,那么使用css will-change关键字是没有害处的/而是改为。

答案 5 :(得分:0)

尝试基于每秒最大事件的方法:

jQuery(document).ready(function(){
   var now, then, delta, interval = 1000/60; //maximum 60 eps, you can change
   //$("#special").click(function(e){
   $(".imgWrap").mousemove(function(e){
     now = Date.now();
     delta = now - then;
     if (delta > interval) {
       then = now - delta % interval; //subtract extra waited time
       //$('#status2').html(e.pageX +', '+ e.pageY);
       //alert(e.pageX + ', ' + e.pageY);
       mouseX = e.pageX;
       mouseY = e.pageY;
       // do your thing
     }
   }); 
})
编辑:不知道javascript中是一个保留字,你可以重命名。

答案 6 :(得分:0)

我有一个可排序的 angular 列表视图,但是在 chrome 中使用鼠标拖动项目滞后很多。我尝试禁用所有 chrome 扩展程序,现在延迟完全消失了。

事实证明是 TamperMonkey 造成的。