在鼠标悬停时保持滑动菜单打开

时间:2011-02-06 20:45:16

标签: jquery animation hover mouseout slidingdrawer

我正在尝试将使用内联Javascript加载的现有菜单系统转换为仅使用jQuery的新的,更高效的代码。

我有一个带翻转图像的水平条。我在页面中有一个包含整数值的隐藏字段。当加载页面时,相应的菜单加载图像的“粘性”版本,并且所有其他菜单项在鼠标输入和输入上交换图像。离开。它装载了大量的内联Javascript和一个怪物Javascript文件,每次创建一个新站点时转换都很繁琐。

我成功将所有内容转换为jQuery,我也可以禁用粘滞菜单项上的点击。现在我可以简单地设置一些变量,并根据每个站点的设计轻松定制它。

工作得很好......

现在出现了一个新问题。一种设计在每个菜单图像下包含一堆滑动抽屉。滑动动画由外部JS文件处理,菜单抽屉本身只是一个包含嵌套在容器DIV中的内容的DIV。

然后我为jQuery编写了一些简单的东西,动画DIV并在鼠标悬停时将其滑入和滑出菜单图像。

问题是我似乎无法解决鼠标从菜单图像移开而进入菜单抽屉而没有抽屉关闭的问题。我理解“为什么?”......我离开的图像触发动画关闭抽屉,然后才能进入。如果我将悬停动画应用于抽屉容器,它只需在菜单下创建一个区域,该区域也会触发动画,我也不想要。它似乎与jQuery变成了一个更复杂的问题。所有这一切都适用于内联Javascript ...您可以将鼠标从图像移动到相邻的打开抽屉而不会触发关闭它的功能...就好像抽屉的内联“鼠标输入”取消了图像的“鼠标离开”。

有什么建议吗?

感谢 - 你!


编辑:

我相信我通过使用.stop(true,false)从图像传递到抽屉时解决了这个问题。这会在动画开始之前停止动画。然后在启动正常动画之前输入图像时相同...这具有停止通过离开抽屉并输入图像而触发的动画的效果,但是在正常输入图像时也没有做任何事情。更多测试然后我会发布一些示例代码。


编辑#2:

我使用“stop()”和“delay()”来控制动画,但是如果你能让鼠标快速进入它,就可以冻结抽屉的开口。安装150毫秒。但现在设置为300毫秒来夸大问题。

此处张贴的相关代码......

jsfiddle.net/qPLVp/8 /


编辑#3:

感谢Neil,现在这个功能非常好。通过更快的动画速度,鼠标超出菜单图像并进入抽屉的状态将保持最小。但是如果它碰巧发生了,抽屉就不会关闭,这比从鼠标下面关闭要好得多。

http://jsfiddle.net/elusien/PayFw/8/


编辑#4:

再次感谢Neil,这是相同代码的更高效版本......

http://jsfiddle.net/PayFw/9/

5 个答案:

答案 0 :(得分:1)

我修改了你的jsFiddle代码以使其正常工作。基本上我已经将数据对象附加到#menu元素。打开此抽屉时,对象为{opening: true}。当抽屉完全打开(动画完成)时,对象为{opening: false}。当你进入抽屉时检查这个,如果它是假的,我停止动画。如果确实如此,我不会停止动画。

代码是:

    function enter(event) { // mouseenter IMG
        // removed image rollover code

        $('#menu').data({opening: true}).stop(true, false).animate({
            top: '0',
            opacity: 1
        },{
            duration: 300  // slow the opening of the drawer
        },
        function(){$(this).data({opening: false});}
        );
    };
    function leave(event) { // mouseout IMG
        // removed image rollover code

        $('#menu').delay(400).animate({
            top: '-'+$ht+'px',
            opacity: 0
        },{
            duration: 600
        });
    };

    $('#menu').hover(
        function (){ // mouseenter Menu drawer
            if (!$(this).data('opening')) {
                $(this).stop(true, false);
            }
        },
        function (){ // mouseout Menu drawer
            $(this).delay(400).animate({
                top: '-'+$ht+'px',
                opacity: 0
            },{
                duration: 600    
            });

       }
   );

现在工作正常。考虑到这一点,你可能想要重做一些“延迟”。

答案 1 :(得分:1)

Sparky的,

我想出了一种不同的做事方式。基本上在“按钮”和“描述”上放置一个透明蒙版,并在此上使用“mouseleave”事件。

HTML:

<body>
<div id="Container" class="menuContainer" style="position: relative">
<div id="menumask">&nbsp;</div>
<!-- this simulates the menu rollover image -->
<div id="menuitem" style="position:absolute; background-color:#ff00ff; top:10px; width:200px; height:50px; text-align:center;">
    <b>MENU ITEM</b>
</div>

<!-- this is the drawer -->
    <div id="menu" class="menuContent">
        <br/>
        <p>Content of the menu drawer.</p>
        <br/>
        <p>Bla bla bla </p>
        <br/>
        <p>Bla bla bla Bla.</p>
        <br/>
        <p>Bla bla bla Bla bla.</p>
        <br/>
        <p>Bla bla bla Bla bla bla Bla bla.</p>
    </div>

使用Javascript:

$(document).ready(function() {
    $('#menuitem').bind('mouseenter', enter);
    $('#menumask').bind('mouseleave', leave);

    $('#menu').css({
        height: '500px',
        position: 'absolute',
        paddingTop: '50px',
        width: '200px',
        backgroundColor: '#080',
        zIndex: -1
    }).hide();
    $('#menumask').css({
        height: '550px',
        width: '200px',
        opacity: 0.99,
        position: 'absolute',
        fontSize: '20000px',
        overflow: 'hidden',
        zIndex: 2
    }).hide();

    function enter(){
        $('#menumask').show();
        $('#menu').stop(true,true).animate({height: 500}, 'slow');
    };
    function leave(){
        $('#menumask').hide();
        $('#menu').stop(true,true).slideUp({height:   0}, 'slow');};  
});

您可以将此作为菜单系统的基础。

此致        尼尔

答案 2 :(得分:0)

看起来你正在寻找.delegate()函数,该函数现在或将来将处理程序附加到DOM事件:

$(".menuItem").delegate(".subMenu","hover", function(){ $(this).show(); });

您可以在此处详细了解.delegate()函数及其好友.live():http://api.jquery.com/delegate/

答案 3 :(得分:0)

如果没有看到代码,很难知道以下内容是否有效:

hover()将2个函数作为其参数,第一个是在输入图像时执行的,第二个是;当你离开图像时。

您可能已将第二个功能设置为隐藏(关闭)抽屉。我会在delay(100)之前添加一个小延迟(例如hide())并在抽屉本身上设置一个悬停事件(在第一个函数参数中)停止动画队列stop(true, true) - 这将停止抽屉关闭,在第二个功能中 - 退出时关闭抽屉。

答案 4 :(得分:0)

嘿我在尝试完成同样的事情时偶然发现了这篇文章。以为我可能会留下我的解决方案,因为它现在是2017年,.delegate已被弃用,并且使用数据来跟踪转换是否仍然有效似乎很混乱。

关键是使用传入mouseleave回调的元素来获取element.relatedTarget

$('.myMouseoverElements').on('mouseover', function() {        

  activeElements = $('.elements.to.open')
  activeElements.addClass('open')

  activeElements.on('mouseleave', function(element) {

    var sustainElements = $('.elements.to.sustain.mouseover')
    var drawerShouldClose = !$(element.relatedTarget).is(sustainElements)

    if (drawerShouldClose) {
      activeElements.removeClass("open")
      activeElements.off("mouseleave")
    }
  })
})

感谢您的帮助!