1

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

我目前正在获得鼠标在 mousemove 上的位置,然后使用它来移动我的 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 标签的位置更改为鼠标的位置。

实际上,你可以在这里查看:pokemonsite

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

4

7 回答 7

6

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

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

  2. 使用 CSStransform函数进行绝对定位以避免重绘,但保持弹出框元素绝对或固定定位。

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

  4. (也许,可选)悬停时隐藏光标并使用弹出元素作为位置指示器。

  5. 将所有可以从 JS 移到 CSS 的东西,即。:hoverstate 可用于切换弹出框元素的显示。

我做了演示示例,结合了列出的所有内容。光标位置和弹出图像之间仍然存在一些延迟,原始问题中的示例链接都不起作用,所以我无法与之比较,但我希望有人觉得这很有用。

演示

<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)' });
}

参考:

于 2015-03-25T18:12:49.513 回答
3

尝试这个:

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

     mouseX = e.pageX;
     mouseY = e.pageY;
    }); 
})
于 2015-03-25T06:45:12.697 回答
2

使用e.offsetXand e.offsetYor(推荐)e.clientXande.clientY代替 pageX 和 pageY。也许这将是一个更好的解决方案。注意:据我所知offsetxoffsety不要在 Firefox 中工作。

于 2015-03-21T23:17:01.610 回答
2

如果绝对 (x, y) 位置不是那么重要(意思是:可以在不破坏逻辑的情况下省略某些像素值),您可以尝试跳过鼠标移动事件的某些帧。

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-event 上重新绘制图像,而是do_stuff仅每 5 个事件调用一次您的 draw-routines ( )。

于 2015-03-20T11:13:54.507 回答
2

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

用于requestAnimationFrame处理更新 - 如果您有一个普通函数并将其作为回调传递,那么它每帧只会被调用一次(即,不要使用匿名函数)。

最后利用 usetransform:translate(x,y)来设置位置,更好地利用 GPU 等。与此相关,will-change如果你想使用 top/left 来代替,使用 css 关键字也没有什么坏处。

于 2015-03-26T10:23:09.913 回答
1

try a maximum event per second based approach:

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
     }
   }); 
})

EDIT: didn't know then is a reserved word in javascript, you can rename it.

于 2015-03-26T23:42:15.153 回答
0

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

原来是 TamperMonkey 造成的。

于 2021-02-25T12:09:28.563 回答