【问题标题】:Keeping a sliding menu open on mouseover在鼠标悬停时保持滑动菜单打开
【发布时间】:2011-06-22 09:44:51
【问题描述】:

我正在尝试将加载了内联 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/

【问题讨论】:

  • 请向我们展示 jQuery 代码和 HTML 的相关部分,以便我们提供帮助。我想我可以帮忙,但我需要看代码。

标签: jquery animation hover mouseout slidingdrawer


【解决方案1】:

嘿,我在尝试完成同样的事情时偶然发现了这篇文章。我想我可能会放弃我的解决方案,因为现在是 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")
    }
  })
})

感谢您的帮助!

【讨论】:

    【解决方案2】:

    如果没有看到代码,很难知道以下是否可行:

    hover() 有两个函数作为参数,第一个在输入图像时执行,第二个;当你离开图像时。

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

    【讨论】:

    • 谢谢你,尼尔!......我在阅读你的答案之前想出了“停止”,但你对小延迟的想法似乎是一个非常聪明的补充。我必须使用“stop(true, false)”,因为我不希望取消的动画完成。似乎可以在 Safari 和 Firefox 中使用...接下来在资源管理器中进行测试。
    • StackOverflow 的新手,所以不知道在哪里发布我的所有代码...我解决了一个小问题...如果我在图像打开时将鼠标移到图像上并进入抽屉,它冻结了。我让它打开得很快(200)以减少这种情况,但它存在。
    • 您可以将您的代码放在问题本身中(在执行此操作时使用“代码”符号)。或者更好的是,将它与 HTML 和 CSS 一起放在“www.jsfiddle.net”上,并发布保存时获得的网址,以便人们可以轻松地“玩”它。
    • 关于“冻结”,你有没有尝试增加延迟,比如250?
    • 另外,您可能需要在将 HOVER 拖入抽屉时稍作延迟,这样您就不会像现在一样过早终止动画并冻结。
    【解决方案3】:

    我已经修改了您的 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    
                });
    
           }
       );
    

    现在可以正常工作了。鉴于此,您可能想重做一些“延迟”。

    【讨论】:

    • jsfiddle.net/PayFw Hi Neil- 以上确实解决了冻结的问题。但是,现在当动画完成后鼠标移入抽屉时抽屉将不会保持打开状态。将鼠标悬停在菜单图像上并等待抽屉打开。将鼠标向下移动到抽屉中,抽屉关闭。你确实让我走上了正确的道路,并且通过一些调整,我想我可以让它发挥作用。谢谢!
    • 根据您之前的代码,我有一个想法,尼尔...让我整理一下,如果我卡住了,我会大喊...感谢您的时间,但您的工作毫无意义如果我要解决这个问题。无论哪种方式,我都会回帖。
    • Neil- 我重写了它,我认为我有一些很酷的东西,但是移动鼠标太快会破坏它。你拥有它的方式,回调函数永远不会触发(我认为是语法问题)。那部分是固定的。现在,当您在动画期间超出菜单图像时,抽屉会停止并关闭。只有在抽屉完全打开时,您才能在抽屉内移动。 (理想情况下,我希望抽屉在动画期间鼠标进入时刚刚完成打开并保持打开状态)。增加持续时间将减少失败的机会。也对你的智慧感兴趣...link
    • 哦,(关于前面评论中的 JSFiddle),在打开的抽屉和菜单图像之间来回移动太快会导致抽屉关闭。这似乎比预期更具挑战性。
    • 嗨,我已经解决了这个问题。见jsfiddle.net/elusien/PayFw/8。它停止了展示,而不是隐藏。您需要 stop(true, true) 并对数据对象进行其他一些更改。查看代码。祝你好运。
    【解决方案4】:

    闪闪发光,

    我想出了一种不同的做事方式。基本上在“按钮”和“描述”上放置一个透明蒙版,并在上面使用“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');};  
    });
    

    您可以将其用作菜单系统的基础。

    问候 尼尔

    【讨论】:

    • 感谢尼尔所做的一切!一旦我有机会尝试一下,我会回帖。
    • 这段代码看起来很不错,但是对于这个站点,我不愿意为每个按钮都做一个掩码。但是,它将为将来的站点保存,因为它确实解决了这个概念的许多问题。谢谢!
    【解决方案5】:

    您似乎正在寻找 .delegate() 函数,它将处理程序附加到现在或将来的 DOM 事件:

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

    您可以在此处阅读有关 .delegate() 函数及其伙伴 .live() 的更多信息:http://api.jquery.com/delegate/

    【讨论】:

    • 有趣。你认为这比我玩的“停止”更好吗? (见我上面的编辑和下面尼尔的建议)。代表对我来说是新手,我很难理解它。
    猜你喜欢
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-20
    • 2011-02-06
    相关资源
    最近更新 更多