如何让 .hover() 函数等待?

49

我有一个下拉菜单。现在当它滑到多个级别时,我希望在它消失之前等待大约2秒钟,以便用户可以在他错误地中断 .hover() 后重新进入。

这可行吗?

我的幻灯片代码:

$('.icon').hover(function() {
        $('li.icon > ul').slideDown('fast');
    }, function() { 
        $('li.icon > ul').slideUp('fast');
    });
9个回答

75

这会使第二个函数在执行前等待2秒钟(2000毫秒):

$('.icon').hover(function() {
    clearTimeout($(this).data('timeout'));
    $('li.icon > ul').slideDown('fast');
}, function() {
    var t = setTimeout(function() {
        $('li.icon > ul').slideUp('fast');
    }, 2000);
    $(this).data('timeout', t);
});

它还清除了超时,以避免疯狂的行为,当用户再次悬停时。然而,这并不是一个非常优雅的方法。你应该查看hoverIntent插件,它专门设计用来解决这个问题。

这应该是第一个答案。 - Ronan
1
嗨。我正在尝试在jsFiddle中使用slideDown()slideUp(),但是slideUp()不起作用。你能告诉我这里缺少了什么吗?注意:我正在尝试在不使用hoverIntent()函数的情况下完成它。 - Himanshu
@him056,你在jsFiddle中遇到了作用域问题。这里可以正常工作:http://jsfiddle.net/671noauq/。 - Adam
jQuery插件在TypeScript中不太兼容,所以这是我的解决方案。 - StingyJack

43

个人而言,我喜欢"hoverIntent"插件:

http://cherne.net/brian/resources/jquery.hoverIntent.html

在该页面上,hoverIntent是一个插件,它试图确定用户的意图……就像水晶球一样,只是用鼠标移动代替!它的工作方式类似于(并派生自)jQuery内置的hover。然而,它不会立即调用onMouseOver函数,而是等待用户的鼠标足够减速后再进行调用。

为什么?为延迟或防止动画或ajax调用的意外触发。简单的超时定时器可用于小区域,但如果目标区域较大,则可能无论用户有没有意图都将执行。

var config = {    
 sensitivity: 3, // number = sensitivity threshold (must be 1 or higher)    
 interval: 200, // number = milliseconds for onMouseOver polling interval    
 over: makeTall, // function = onMouseOver callback (REQUIRED)    
 timeout: 500, // number = milliseconds delay before onMouseOut    
 out: makeShort // function = onMouseOut callback (REQUIRED)
};
$("#demo3 li").hoverIntent( config ) 

配置选项

sensitivity: 如果鼠标在轮询间隔之间移动的像素少于此数字,则将调用“over”函数。最低灵敏度阈值为1,鼠标必须在轮询间隔之间不移动。使用更高的灵敏度阈值,您更有可能收到误报。默认灵敏度:7

interval: hoverIntent在读取/比较鼠标坐标之间等待的毫秒数。当用户的鼠标首次进入元素时,记录其坐标。可以在单个轮询间隔后最早调用“over”函数。将轮询间隔设置得更高将增加第一个可能的“over”调用之前的延迟,但也会增加下一个比较点的时间。默认间隔:100

over: 必需。您想要在onMouseOver上调用的函数。您的函数将接收与jQuery的hover方法相同的“this”和“event”对象。

timeout: 在“out”函数被调用之前的简单延迟(以毫秒为单位)。如果用户在超时时间过期之前再次将鼠标移到元素上,那么“out”函数将不会被调用(“over”函数也不会被调用)。这主要是为了防止松散/人类鼠标轨迹暂时(无意地)使用户离开目标元素...给他们时间返回。默认超时:0

out: 必需。您想要在onMouseOut上调用的函数。您的函数将接收与jQuery的hover方法相同的“this”和“event”对象。请注意,只有在同一运行中调用了“over”函数,hoverIntent才会调用“out”函数。


我使用这个工具已经很多年了,直到我意识到对于像这个问题这样的情况来说它有些过度。本主题中的手动代码示例运行良好。 - Jonas Lundman

1

一般的想法是使用setTimeout,像这样:

$('.icon').hover(function() {
           $('li.icon > ul').slideDown('fast');
    }, function() { 
           setTimeout(function() {
                $('li.icon > ul').slideUp('fast');
           }, 2000);
    });

但是如果用户快速移开鼠标然后再次移入,这可能会产生违反直觉的结果——这没有考虑当用户再次悬停在上面时清除超时。这需要额外的状态。


1
以下代码将阻止滑动触发2秒钟:
$('.icon').hover(function() {
  $('li.icon > ul').delay(2000).slideDown('fast');
}, function() { 
  $('li.icon > ul').slideUp('fast');
});

我认为这基本上实现了相反的效果:悬停动作不会立即触发,但必须悬停至少2秒钟才会有任何反应。仍然有用,但不完全是问题的答案。我错了吗? - Simon Steinberger

1
$('.icon').on("mouseenter mouseleave","li.icon > ul",function(e){
   var $this = $(this);
   if (e.type === 'mouseenter') {
       clearTimeout( $this.data('timeout') );
       $this.slideDown('fast');
   }else{ // is mouseleave:
       $this.data( 'timeout', setTimeout(function(){
           $this.slideUp('fast');
       },2000) );  
   }
 });

1

或者你可以简单地使用 transition:all 2s ease-in-out。 确保为不同的浏览器添加-webkit,-moz和-o。


0
我想补充一下Paolo Bergantino的观点,你可以不使用data属性来实现这个功能:
var timer;
$('.icon').hover(function() {
    clearTimeout(timer);
    $('li.icon > ul').slideDown('fast');
}, function() {
    timer = setTimeout(function() {
        $('li.icon > ul').slideUp('fast');
    }, 2000);
});

0
var timer;

var delay = 200;

$('#hoverelement').hover(function() {

    on mouse hover, start a timeout

    timer = setTimeout(function() {

       Do your stuff here 

    }, delay);

}, function() {

   Do mouse leaving function stuff here    

    clearTimeout(timer);
});

//编辑:插入代码


0

我认为这是你需要的代码:

    jQuery( document ).ready( function($) {  
    var navTimers = [];  
    $('.icon').hover(function() { 
            var id = jQuery.data( this );  
            var $this = $( this );  
            navTimers[id] = setTimeout( function() {  
                $this.children( 'ul' ).slideDown('fast');  
                navTimers[id] = "";  
            }, 300 );  
        },  
        function () {  
            var id = jQuery.data( this );  
            if ( navTimers[id] != "" ) {  
                clearTimeout( navTimers[id] );  
            } else {  
                $( this ).children( "ul" ).slideUp('fast'); 
            }  
        }  
    );  
}); 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接