【问题标题】:Problem with a jQuery script that sets an active element on hover and animation callbacks在悬停和动画回调上设置活动元素的 jQuery 脚本问题
【发布时间】:2011-07-21 11:37:26
【问题描述】:

我在一个网站上工作,其中有一系列元素,并且在任何时候都只有一个元素必须处于活动状态。当该元素处于活动状态时,会显示一个“详细信息”div。

当您将鼠标悬停在这些元素上时,它们会变得活跃,但正如我所说,它们中只有一个可以同时处于活跃状态。我目前正在使用活动类设置活动元素。

在我当前的代码中,当用户将鼠标悬停在任何元素上时会发生这种情况:

  • 前一个活动元素移除了“活动”类,并且淡出
  • 在fadeOut 回调中,悬停的元素变为活动状态(获取“活动”类),并且是fadeIn
  • 如果当前没有活动元素,则悬停元素变为活动元素(“活动”类)并淡入

这没问题,但是当您在元素之间快速悬停时,会有一个短暂的时刻没有元素处于活动状态,因此不仅仅是元素获得活动类并显示出来。

你会如何解决这个问题?

这是我的代码:

function setActive(selected) {


    //stores the active element in a variable
    active = selected;

    //checks if there are currently elements with the 'active' class in the DOM
    if ( $('#info article.active').length > 0) {

        //if there is any currently active element, and its element_id attribute is not the one stored in the active variable
        //it gets the 'active' class removed, its hidden, and in the callback of the animation
        //the newly selected element gets the class 'active' and is shown with fadeIn

        $('#info article.active[element_id!="' + selected + '"]').removeClass('active').fadeOut('fast', function(){
            $('#info article[element_id="' + selected +'"]').addClass('active').fadeIn('normal');
            }); 

    } else {

        //if there is no current active element, the newly selected one is applied the class active, and shown with fadeIn

        $('#info article[element_id="' + selected +'"]').addClass('active').fadeIn('normal');
    }
}

【问题讨论】:

    标签: javascript jquery


    【解决方案1】:

    鼠标飞越和/或挑剔的目标上的杂散(错误)射击是一个常见问题。标准解决方案是在悬停“粘住”之前稍作延迟。

    重要提示:问题没有显示setActive() 是如何被调用的!

    但是如果你像这样构造 HTML:

    <div id="flyOverControls">
        <ul>
            <li rel="Article_1">Show 111</li>
            <li rel="Article_2">Show 222</li>
            <li rel="Article_3">Show 333</li>
            <li rel="Article_4">Show 444</li>
        </ul>
    </div>
    <div id="info">
        <article id="Article_1">First article.</article>
        <article id="Article_2">Second article.</article>
        <article id="Article_3">Third article.</article>
        <article id="Article_4">Fourth article.</article>
    </div>
    


    然后像这样激活控件:

    $("#flyOverControls li").hover (function (zEvent) {setActiveArticle (zEvent); } );
    


    那么这段代码应该可以解决问题。根据口味调整速度。就个人而言,我会杀死淡出。

    function setActiveArticle (zEvent)
    {
        var dDelay;
        var ActionFunction  = null;
        var targetID        = $(zEvent.currentTarget).attr ('rel');
    
        if (zEvent.type == 'mouseenter')
        {
            //--- Hovering over a new article control... Pause for an ergo delay.
            dDelay          = 300;
            ActionFunction  = function (targetID, context) {
                //--- If we are setting the same article, then nothing needs be done here.
                if ( ! (context.lastArticle  &&  context.lastArticle == targetID) ) {
                    //checks if there are currently elements with the 'active' class in the DOM
                    if ( $('#info article.active').length > 0) {
    
                        /*  If there is any currently active element, and its element_id attribute is not the one stored in the
                            active variable it gets the 'active' class removed, it's hidden, and in the callback of the animation
                            the newly selected element gets the class 'active' and is shown with fadeIn.
                        */
                        $('#info article.active').removeClass ('active').fadeOut ('fast', function () {
                            $('#info article#' + targetID).addClass ('active').fadeIn ('normal');
                        } );
    
                    } else {
                        //if there is no current active element, the newly selected one is applied the class active, and shown with fadeIn
    
                        $('#info article#' + targetID).addClass ('active').fadeIn ('normal');
                    }
                    context.lastArticle = targetID;
                }
            };
        }
        else //-- zEvent.type == 'mouseleave'
        {
            //--- Done hovering, no action is needed, other than to wait, in case of user jitter.
            dDelay          = 200;
            ActionFunction  = function (targetID, context) {
                var noOp    = 0;
            };
        }
    
        if (typeof this.delayTimer == "number")
        {
            clearTimeout (this.delayTimer);
        }
        context             = this;
        this.delayTimer     = setTimeout (function() { ActionFunction (targetID, context); }, dDelay);
    }
    


    See it in action at jsFiddle.

    【讨论】:

      【解决方案2】:

      如果可以的话,用html在jsfiddle中设置一个链接,这样我可以更详细的看一下。

      但我认为您的问题是由fadeIn 和/或fadeOut 的动画引起的。尝试在动画时停止悬停,$('selector').is(':animated') == false,例如

      更新

      function setActive(selected) {
          //*******if animate is happening, hide elements and removes class
          if ($('#info article').is(':animated')) {
              $('#info article.active').removeClass('active').hide();
          }
          //*******Check if everything is not animated and do hover
          if (!$('#info article').is(':animated')) {
              //stores the active element in a variable
              active = selected;
      
              //checks if there are currently elements with the 'active' class in the DOM
              if ($('#info article.active').length > 0) {
      
                  //if there is any currently active element, and its element_id attribute is not the one stored in the active variable
                  //it gets the 'active' class removed, its hidden, and in the callback of the animation
                  //the newly selected element gets the class 'active' and is shown with fadeIn
                  $('#info article.active[element_id!="' + selected + '"]').removeClass('active').fadeOut('fast', function() {
                      $('#info article[element_id="' + selected + '"]').addClass('active').fadeIn('normal');
                  });
      
              } else {
      
                  //if there is no current active element, the newly selected one is applied the class active, and shown with fadeIn
                  $('#info article[element_id="' + selected + '"]').addClass('active').fadeIn('normal');
              }
          }
      }
      

      【讨论】:

      • 谢谢你,马克。但这不会使函数在当前事件完成之前忽略新事件吗?我认为理想的行为是停止任何当前活动,并执行最后触发的事件。
      • 没错,所以你需要做的是,使用 ':animated' 方法..检查悬停时是否有动画,立即隐藏。如果没有动画,请检查 non 是否处于活动状态和隐藏状态,然后淡入以正确当前悬停。
      猜你喜欢
      • 2012-06-18
      • 1970-01-01
      • 1970-01-01
      • 2011-05-01
      • 2012-04-18
      • 1970-01-01
      • 2011-08-11
      • 1970-01-01
      • 2016-03-01
      相关资源
      最近更新 更多