悬停隐藏元素会在不久之后重播隐藏动画

Posted

技术标签:

【中文标题】悬停隐藏元素会在不久之后重播隐藏动画【英文标题】:Hovering a hiding element replays the hide animation shortly after 【发布时间】:2012-03-13 23:10:30 【问题描述】:

我有 2 个元素彼此相邻,都是绝对定位的。

<div class="vizual">
  <h1 class="typo">...</h1>
  <a href="#" class="typo">...</a>
</div>

当我将鼠标悬停在第一个元素上时,另一个元素会出现在它旁边。有一些效果和计时器正在运行。

function hoverTransfer(trigger,content)
  var t;
  $(trigger).hover(
    function()
      clearTimeout(t);
      if ($(content).css("display") == "none") 
        $(content).show('slide', direction: 'left', 500);
      
    , function()
      t = setTimeout(function() $(content).hide('slide', direction: 'left', 500), 550);
  );
  $(content).hover(
    function()
      clearTimeout(t);
    , function()
        t = setTimeout(function() $(content).hide('slide', direction: 'left', 500), 550);
  );
;

它应该以某种方式工作,当我将鼠标悬停在两个元素之一上时,第二个元素保持显示。当我将鼠标移出时,它会在一段时间后滑回。

编辑:如果我在隐藏第二个元素时将鼠标悬停在其中一个元素上,它应该滑回全宽。但是我也不能生产...

问题 - 它的行为方式也是不受欢迎的: 当我将鼠标悬停在这些元素之一的进出第二个元素隐藏时,它会在完成后不久再次重播隐藏动画。

我尝试了很多不同的“解决方案”(检查元素是否动画,尝试 .stop() 等,但我永远无法产生所需的功能。

【问题讨论】:

如果您在 jsFiddle 中重现此内容,我认为人们帮助您会容易得多。 :) 另外,你想要的确切效果是什么?到目前为止,您真正提到的只是它没有按您希望的方式工作。 jsfiddle.net/sgrxH 将鼠标悬停在红色框上,将鼠标移出元素,当绿色框滑回时,将鼠标移到其中一个元素上(不要按住它,只需当绿色框向后滑动时穿过它)。 【参考方案1】:

说明

好的,我已经拟定了我认为您所要求的内容。如果这不是您所要求的,希望您或其他人可以从中学到一些东西。 :)

    开始布局 用户将鼠标悬停在元素 1 上,元素 2 随即弹出并开始滑动 此时,用户在元素之间悬停,不应发生重置 用户从其中一个元素(在我的示例中为元素 1)悬停在外面 鼠标未在其中一个元素上停留 n 秒,应该像在 2 中一样滑动。但反向。

我发现如果你先概述需要做什么,就更容易知道需要做什么。

通过这些步骤,我们现在可以定义我们需要什么:

    n 秒过去时,检查鼠标在执行“反向动画”的元素之外多长时间的计时器 MouseIn、MouseOut 事件清除计时器,因此当用户仍悬停其中一个元素时它不会执行反向动画 我们需要为每个组实例设置唯一的计时器,我称之为实例化。含义:我们希望能够在超过 1 个包含 2 个元素的块上执行此操作

解决方案

首先,here's a JSFiddle 供您使用 (here's one without comments)。希望有足够多的 cmets 帮助您度过难关。

当然,这是代码。

javascript

//default variables
var Distance = 300; //px
var BetweenOffset = 10; //px
var MouseOut = 550; //ms
var AnimationTime = 500; //ms
var Timers = new Array();

$(document).ready(function()
    //this is just to add the default distance. I didn't specify it in the CSS, but you can do it just as well
    $("div.container div.element_2").css("left", Distance);
    //adds an attribute "unique-id" with a number, so that the timer can be associated with an element. This is necessary to be able to clear the timer, and is the basics in "instantiation 101"
    $("div.container").each(function(index, parent)
        $(parent).attr("unique-id", index);
    );

    //here's were all the magic happens
    $("div.container div.element_1, div.container div.element_2").mouseenter(function(e)
        //define some local variables
        var parent = $(this).parent();
        var id = parent.attr("unique-id");
        var element1 = parent.children(".element_1");
        var element2 = parent.children(".element_2");
        var destination = element1.width()+BetweenOffset;

        //if element2 isn't visible or is being animated, we're going to stop whatever it's doing and do a beginning animation
        if(!element2.is(":visible") || element2.is(":animated") )
            element2.stop(true).show().animate(
                
                    left: destination,
                    opacity: 1
                ,
                AnimationTime,
                "swing"
            );
        

        //then we're gonna clear the timer associated with this parent
        Timers[id]= clearTimeout(Timers[id]);
    ).mouseleave(function(e)
       var parent = $(this).parent();
       var id = parent.attr("unique-id");
       var element1 = parent.children(".element_1");
       var element2 = parent.children(".element_2");

       //here we set the timer using an anonymous function
       Timers[id] = setTimeout(function()
            //Only animate if it's already showing
            if(element2.is(":visible"))
                //stop whatever it's doing and remove the animation queue
                element2.stop(true).animate(
                    
                        "left": Distance,
                        opacity: 0
                    ,
                    AnimationTime,
                    "swing",
                    function()
                        //here we make sure it's not being displayed
                        element2.css("display", "none");
                    
                );
                       
       , MouseOut);
    );
);

html

<div class="container">
    <div class='element_1'>Element 1</div>
    <div class='element_2'>Element 2</div>
</div>
<div class="container">
    <div class='element_1'>Element 1</div>
    <div class='element_2'>Element 2</div>
</div>
<div class="container">
    <div class='element_1'>Element 1</div>
    <div class='element_2'>Element 2</div>
</div>
<div class="container">
    <div class='element_1'>Element 1</div>
    <div class='element_2'>Element 2</div>
</div>
<div class="container">
    <div class='element_1'>Element 1</div>
    <div class='element_2'>Element 2</div>
</div>

CSS

.container
    position: relative;
    height: 50px;
    margin-top: 20px;


.element_1, .element_2
    position: absolute;
    height: 50px;
    left: 0px;
    top: 0px;


.element_1
    border: 1px solid blue;


.element_2
    border: 1px solid red;
    display: none;

参考文献

对我使用的函数的一些参考

.parent() .children() .stop() .animate() .mouseenter() .mouseleave() .attr() setTimeout() & clearTimeout() What is instantiation?

最后的想法

我添加了一些很酷的不透明度过渡,这不是必需的,但是……嗯。 希望这会对您有所帮助,可能有替代我给您的方法,但这是我的解决方法。

编辑

经过简短讨论后,OT 通知了我他的 JSFiddle。我看了看,this is what I got。剩下的唯一问题是它在动画时没有动画,但这是一个没有多少用户注意到的小问题。

【讨论】:

哇,我真的没想到有人会走这么远来提供帮助!在 OP 的 cmets 中,我发布了一个更清晰的 jsfiddle 链接,但即使没有它,您的解决方案也非常接近......第二个元素应该从第一个元素出现。 1 页上只有 1 个实例,因此在这种情况下不需要这些变量......我会尝试根据我的需要对其进行修改,然后告诉你它是如何进行的。无论如何+1,谢谢! @SqueezCZ 我的例子应该可以解决你的问题。查看计时器以及如何处理它们。我没有注意到你的jsfiddle,我会看看它。此外,每个帖子的顶部都会给出+1,并通过单击同一位置的绿色复选标志给出正确答案。感谢代表。 :) @ShadowScripter - 实际上,我的声誉似乎太低了,无法给你 +1。当我到达那里时,我会这样做!无论如何,您认为您可以在查看 jsfiddle 后修改答案吗?我不需要在更多情况下使用它,这样可以更容易地重写它。我在脚本方面不是“新手”,但我认为我无法修改你的脚本来为我工作,我还没有达到那个水平,但我害怕......我会很感激很多 @SqueezCZ 好的,我已经用你的 JSFiddle 版本更新了帖子。 @ShadowScripter - 差不多了!我们都在我们的编辑信息中声明了“在动画期间返回全宽”功能尚未创建。你认为有一些不太复杂的解决方案吗?

以上是关于悬停隐藏元素会在不久之后重播隐藏动画的主要内容,如果未能解决你的问题,请参考以下文章

如何在 jQuery 中隐藏循环元素

jQuery悬停隐藏在子元素上

CSS - 为啥不:悬停父隐藏子元素

记录一个小点react+antd:支持css3的transition动画的一些属性列表

当我在 SVG 中将鼠标悬停时,如何显示和隐藏同级元素?

Selenium WebDriver MoveToElement - 隐藏元素、悬停和切换类