悬停隐藏元素后不久将重放隐藏动画

时间:2012-02-23 14:23:18

标签: jquery animation timer hover slide

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

<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()等等,但我无法生成所需的功能。

1 个答案:

答案 0 :(得分:3)

说明

好吧,我已经制定了我认为你要求的东西。如果这不是你要求的,希望你或其他人可以从中学到一些东西。 :) hovering stuff

  1. 开始布局
  2. 用户将鼠标悬停在元素1上,然后元素2弹出并开始滑动'
  3. 此时,用户在元素之间悬停,不会发生重置
  4. 用户从其中一个元素中悬停,在我的示例中,元素1
  5. 鼠标在n秒内没有超过其中一个元素,应该像在2中那样滑动,但反过来。
  6. 如果您首先概述需要什么,我会发现更容易知道需要做些什么。

    完成这些步骤后,我们现在可以定义我们需要的内容:

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

      解决方案

      首先,here's a JSFiddle让你玩(here's one without comments)。希望有足够的评论来帮助您完成它。

      当然,这是代码。

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

      参考

      对我使用的函数的一些引用

      最后的想法

      我添加了一些很酷的不透明度过渡,没有必要,但是.. meh。 希望这会对你有所帮助,可能有我给你的替代方案,但这就是我解决它的方法。

      修改

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