javascript - 为什么这个动画断断续续,有时在执行之前有很长的延迟?

标签 javascript jquery jquery-animate

这个 jquery 动画在 Firefox 中非常不稳定,在 Firefox 和 chrome 中,它在实际开始动画之前经常有明显的延迟(~1 秒)(如果我在调用 onclick 处理程序时将代码写入控制台) ,会立即显示,但动画调用会有延迟)。这种延迟并非每次都会出现,但如果您点击大约 5-6 次,您至少会看到一次。

<!doctype html>
<html>
    <head>
    <title>Test Lag</title>

    <script type="text/javascript" src="http://code.jquery.com/jquery-1.7.1.min.js"></script>

    <style>
        .base
        {
            position: absolute;
            top: 507px;
            left: 0px;
            width: 1000px;
            height: 40px;
            z-index: 0;
        }

        .one
        {
            position: absolute;
            top: 2px;
            left: 2px;
            width: 994px;
            height: 34px;
            background-color: #ffffff;
            border: solid 1px #505050;
            z-index: 3;
            opacity: 0.5;
            filter: alpha(opacity=50);
        }

        .oneA
        {
            position: absolute;
            top: 0px;
            left: 0px;
            width: 966px;
            height: 6px;
            margin: 10px;
            background-color: #999999;
            border: solid #cccccc 4px;

        }

        .two
        {
            position: absolute;
            top: 1px;
            left: 1px;
            width: 996px;
            height: 36px;
            background-color: #e8e8e8;
            border: solid 1px #505050;
            z-index: 2;
            opacity: 0.25;
            filter: alpha(opacity=25);
        }

        .three
        {
            position: absolute;
            top: 0px;
            left: 0px;
            width: 998px;
            height: 38px;
            background-color: #e8e8e8;
            border: solid 1px #505050;
            z-index: 1;
            opacity: 0.12;
            filter: alpha(opacity=12);
        }

        .four
        {
            position: absolute;
            top: 17px;
            left: 17px;
            width: 966px;
            height: 6px;
            background-color: #e8e8e8;
            z-index: 0;
            opacity: 0.5;
            filter: alpha(opacity=50);
        }

        .five
        {
            position: absolute;
            top: 17px;
            left: 17px;
            width: 966px;
            height: 366px;
            z-index: 4;
            overflow: hidden;
        }
    </style>
    </head>
    <body>

    <div id ="base" class="base">
        <div id="one" class="one">
        <div id="oneA" class="oneA"></div>
        </div>
        <div id="two" class="two"></div>
        <div id="three" class="three"></div>
        <div id="four" class="four"></div>
        <div id="five" class="five">There's some text in here.</div>
    </div>

    <script>
       var isOn = false;

       var jq_base = $('#base');
       var jq_one = $('#one');
       var jq_oneA = $('#oneA');
       var jq_two = $('#two');
       var jq_three = $('#three');
       var jq_four = $('#four');

       var baseTop = 96;
       var baseStartTop =507;

       var baseHeight = 400;
       var oneHeight = 394;
       var oneAHeight = 366;
       var twoHeight = 396;
       var threeHeight = 398;
       var fourHeight = 366;

       var baseStartH = 40;
       var oneStartH = 34;
       var oneAStartH = 6;
       var twoStartH = 36;
       var threeStartH = 38;
       var fourStartH = 6

       document.onclick = function()
       {
           //It's opened
           if ( isOn )
           {
               jq_one.animate( { height: oneStartH }, { duration: 300, queue: false } );
               jq_oneA.animate( { height: oneAStartH }, { duration: 300, queue: false } );
               jq_two.animate( { height: twoStartH }, { duration: 300, queue: false } );
               jq_three.animate( { height: threeStartH }, { duration: 300, queue: false } );
               jq_four.animate( { height: fourStartH }, { duration: 300, queue: false } );
               jq_base.animate(
                   { height: baseStartH },
                   {
                       duration: 300,
                       queue: false,
                       step: function (now)
                       {
                           if ( now <= ( baseStartH + 10 ) ) jq_base.animate( { top: baseStartTop }, 800 );
                       }
                   }
               );

               isOn = false;
           }

           //It's closed
           else
           {
               jq_base.animate(
                   { top: baseTop },
                   {
                       duration: 800,
                       step: function (now)
                       {
                           if ( now <= 100 )
                           {
                               jq_base.animate( { height: baseHeight }, { duration: 300, queue: false } );
                               jq_one.animate( { height: oneHeight }, { duration: 300, queue: false } );
                               jq_oneA.animate( { height: oneAHeight }, { duration: 300, queue: false } );
                               jq_two.animate( { height: twoHeight }, { duration: 300, queue: false } );
                               jq_three.animate( { height: threeHeight }, { duration: 300, queue: false } );
                               jq_four.animate( { height: fourHeight }, { duration: 300, queue: false } );
                           }
                       }
                   }
               );
               isOn = true;
           }
       }
    </script>
    </body>
</html>

演示:http://jsfiddle.net/fnswz/

最佳答案

我认为问题出在if (isOn)分支的以下部分:

  jq_base.animate(
      { height: baseStartH },
      {
          duration: 300,
          queue: false,
          step: function (now)
          {
              if ( now <= ( baseStartH + 10 ) )
                 jq_base.animate( { top: baseStartTop }, 800 );
          }
      }
  );

具体来说,在该特定 animate() 调用的 step 函数中,您将启动另一个持续时间相当长(800ms)的动画,并且因为它位于 step,即使使用 if 测试,您也会启动多个持续时间较长的动画。

这意味着,尽管该过程到达了看起来已完成的点,因为一切都已移至最终位置,但在幕后,这些额外的动画尚未完成运行,因此它不会响应正确地适应后续点击。如果您将 800 毫秒的动画移出 step 函数并简单地将其放在后面,似乎会使一切工作更加顺利。 (至少,在 Chrome 中看起来要好得多:正如我在上面的评论中所说,我在这台计算机上没有 FF,所以我无法测试它。)

这是一个包含我正在谈论的更改的演示:http://jsfiddle.net/fnswz/1/

您可能需要在启动动画时设置一个标志 animationRunning,然后使用 animate()complete 回调取消设置,这样您就可以测试该标志并忽略点击,直到当前动画完成为止,但只是上面的更改对我来说就取得了很大的进步。

(顺便问一下,当你使用 jQuery 时,为什么要使用 document.onclick = ... ?)

关于javascript - 为什么这个动画断断续续,有时在执行之前有很长的延迟?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8765778/

相关文章:

javascript - Angular $scope 变量未在 Controller 中更新

javascript - AngularJS: "isolate scope"还是 "isolated scope"?

javascript - 网站加载前的欢迎屏幕(点击进入)[Splash Screen]

javascript - 使用 angularjs 的货币转换器

javascript - CSS 和 jQuery : Element moving Element

javascript - 使用 jquery 显示和隐藏叠加层

asp.net - IsClientScriptIninclude注册的问题

javascript - 如何从 Wordpress 一页中删除#

javascript - jQuery 事件处理程序不工作

jquery - 如何使用 jquery animate 配置滚动速度?