JS / jQuery性能不佳,特别是在IE9和Firefox中

时间:2012-10-19 15:58:55

标签: javascript jquery performance

我有严肃的视觉和视力以下脚本的性能问题。最大的问题是对象的动画变得非常生涩,在IE9中几乎是瘫痪,但在Firefox中越来越烦人。

直到最近它一直很快 - 但我担心复杂性正在减慢速度。奇怪的是,Sunspider benchmark在我的IE9实例中比在Firefox中运行得更快。

脚本(更大集合的片段***):

  1. 检查用户进程的HTML5会话存储日志 游戏。
  2. 根据舞台,在两个动画之间设置动画 使用crSpline分。
  3. 确保浏览器窗口跟随对象 穿过大画布,通过scrollLeft等。
  4. 最后,它通过colorbox加载弹出窗口。
  5. 当此框关闭时,用户进度日志会相应增加,对象会再次移动。
  6. 我可以对代码进行明显的速度提升吗?有一点点的回复,我怎么能减少呢?是否有任何无限循环运行,我错过了?有没有我可以使用的软件来描述JS的慢点?

    ***(我无法提供其他JS文件或HTML,但我已将此脚本识别为问题)


    更新 经过相当多的测试后,似乎步骤动画功能 - 通过scrollLeft跟随窗口中的对象 - 导致生涩的动画。删除它会大大改善。

    然而,这不是一个可行的长期解决方案。一个快速解决方法是完成跟随函数调用,但这对最终用户来说是一种不那么流畅的体验,特别是当对象移动距离较远时。

    那么,我如何修改step函数以更慢'/更高效地运行?我猜测它是由于它使用所有可用资源来跟踪每个对象造成的急动毫秒。

    (function ($) {
    
      sessionStorage.gameMainStage = 0 
    
      moveShip =  function() {
    
        switch (sessionStorage.gameMainStage)
    
    {
      case '1':
        $("#object").animate(
          { crSpline: $.crSpline.buildSequence([[715, 425], [582, 524], [556, 646], [722, 688], [963, 629], [1143, 467]]) },{
          duration: 10000,
              step: function() {
                var mover = $('#object'),               
                posX = mover.position().left;
                posY = mover.position().top;
    
                $(window)
                .scrollLeft(posX - $(window).width() / 2)
                .scrollTop(posY - $(window).height() / 2);
              },
              complete: function() {
                $.colorbox({href:"dialog-1.html", width:"737px", height:"474px", iframe: true, overlayClose: false, escKey: false, close: ""});
              }
          }
        );
        break;
    
      case '2':
        $("#object").animate(
          { crSpline: $.crSpline.buildSequence([[1143, 467], [1343, 667], [1443, 367],  [1243, 167], [1499, 285]]) },
            {
              duration: 5000,
              step: function() {
                var mover = $('#object'),               
                posX = mover.position().left;
                posY = mover.position().top;
    
                $(window)
                .scrollLeft(posX - $(window).width() / 2)
                .scrollTop(posY - $(window).height() / 2);
              },
              complete: function() {
                $.colorbox({href:"dialog-2", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""});
              }
    
            }
        );
        break;
    
      case '3':
        $("#object").animate(
          { crSpline: $.crSpline.buildSequence([[1499, 285], [1922, 423]]) },
            {
              duration: 5000,
              step: function() {
                var mover = $('#object'),               
                posX = mover.position().left;
                posY = mover.position().top;
    
                $(window)
                .scrollLeft(posX - $(window).width() / 2)
                .scrollTop(posY - $(window).height() / 2);
              },
              complete: function() {
                $.colorbox({href:"dialog-3.html", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""});
              }
    
            }
        );
        break;  
    
      case '4':
        $("#object").animate(
          { crSpline: $.crSpline.buildSequence([[1922, 423], [2216, 578]]) },{
            duration: 5000,
              step: function() {
                var mover = $('#object'),               
                posX = mover.position().left;
                posY = mover.position().top;
    
                $(window)
                .scrollLeft(posX - $(window).width() / 2)
                .scrollTop(posY - $(window).height() / 2);
                }, 
    
              complete: function() {
                $.colorbox({href:"game-1.html", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""});
              }
            }
        );
        break;
    
      case '5':
        $("#object").animate(
          { crSpline: $.crSpline.buildSequence([[2216, 578], [2769, 904]]) },{
          duration: 5000,
              step: function() {
                var mover = $('#object'),               
                posX = mover.position().left;
                posY = mover.position().top;
    
                $(window)
                .scrollLeft(posX - $(window).width() / 2)
                .scrollTop(posY - $(window).height() / 2);
              }, 
    
              complete: function() {
                $.colorbox({href:"dialog-4.html", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""});
              }
          }
        );
        break;
    
      case '6':
        $("#object").animate(
          { crSpline: $.crSpline.buildSequence([[2769, 904], [3263, 903]]) },{
          duration: 5000,
              step: function() {
                var mover = $('#object'),               
                posX = mover.position().left;
                posY = mover.position().top;
    
                $(window)
                .scrollLeft(posX - $(window).width() / 2)
                .scrollTop(posY - $(window).height() / 2);
              }, 
    
              complete: function() {
                $.colorbox({href:"dialog-5.html", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""});
              }
          }
        );
        break;
    
      case '7':
        $.colorbox({href:"game-2.html", width:"500px", height:"600px", iframe: true, overlayClose: false, escKey: false, close: ""});
      break;
    
      case '8':
        $.colorbox({href:"dialog-6.html", width:"737px", height:"567px", iframe: true, overlayClose: false, escKey: false, close: ""});
      break;
    
      case '9':
        $("#object").animate(
          { crSpline: $.crSpline.buildSequence([[3263, 903], [4141, 820]]) },{
          duration: 5000,
              step: function() {
                var mover = $('#object'),               
                posX = mover.position().left;
                posY = mover.position().top;
    
                $(window)
                .scrollLeft(posX - $(window).width() / 2)
                .scrollTop(posY - $(window).height() / 2);
              }, 
    
              complete: function() {
                $.colorbox({href:"dialog-7.html", width:"737px", height:"547px", iframe: true, overlayClose: false, escKey: false, close: ""});
              }
          }
        );
        break;
    
      case '10':
        $("#object").animate(
          { crSpline: $.crSpline.buildSequence([[4141, 820], [4568, 949], [4447, 1175]]) },{
          duration: 5000,
              step: function() {
                var mover = $('#object'),               
                posX = mover.position().left;
                posY = mover.position().top;
    
                $(window)
                .scrollLeft(posX - $(window).width() / 2)
                .scrollTop(posY - $(window).height() / 2);
              }, 
    
              complete: function() {
                $.colorbox({href:"dialog-8.html", width:"737px", height:"434px", iframe: true, overlayClose: false, escKey: false, close: ""});
              }
          }
        );
        break;
    
      case '11':
        $.colorbox({href:"dialog-9.html", width:"737px", height:"567px", iframe: true, overlayClose: false, escKey: false, close: ""});
      break;
    
      case '12':
        $("#object").animate(
          { crSpline: $.crSpline.buildSequence([[4447, 1175], [4701, 1124], [4816, 822]]) },{
          duration: 5000,
              step: function() {
                var mover = $('#object'),               
                posX = mover.position().left;
                posY = mover.position().top;
    
                $(window)
                .scrollLeft(posX - $(window).width() / 2)
                .scrollTop(posY - $(window).height() / 2);
              }, 
    
              complete: function() {
                $.colorbox({href:"dialog-10.html", width:"900px", height:"687px", iframe: true, overlayClose: false, escKey: false, close: ""});
              }
          }
        );
        break;
    }
    
    };
    
    })(jQuery);
    

5 个答案:

答案 0 :(得分:11)

我担心你使用的图书馆太旧了,不能期待很棒的表演。

我的代码中没有看到任何错误(除了您可以为每个交换机案例使用带有config参数的函数,但这只是一个不会显着影响性能的重构问题)

CrSpline使用左侧和顶部CSS属性。

您可能希望研究利用硬件加速的CSS 2d转换:

使用-webkit/moz/ms-transform: translateX(-1000px) translateY(200px) 而不是left: -1000px; top: 200px;

我认为你可以很容易地在crspline库中重写一些代码朝这个方向发展。

您还可以尝试寻找更新的“样条”库。

另一点:crSpline似乎没有使用requestAnimationFrame功能。 JQuery的animate方法也没有。我建议你看一下TweenLite / TweenMax库:http://www.greensock.com/v12/

为你的工作干杯!

答案 1 :(得分:5)

我遇到了一个连接到window.resize和window.scroll的单页面应用程序的问题。 IE浏览器似乎比其他浏览器慢得多。

我注意到的第一件事是,在IE(特定版本8)中,附加到window.scroll或.resize的回调在调整窗口大小时似乎比Chrome或FF中的响应多了很多倍(或者滚动)。因此,附加的任何回调被称为比Chrome增加相对成本的数倍。

我们设法通过将这些回调中的内容最小化到最小化来解决我们的问题,而我们获得的主要收益是摆脱了jQuery选择器。所以在你的情况下,你在回调函数中有例如var mover = $('#object'),每当你的事件触发时,IE会尝试查找并获取对象并将其包装在jQuery中,只需在你的回调,然后使用缓存的对象。在我们的例子中,按顺序改进了性能,即使没有遇到性能问题也是一件好事(这是一次不必要的重复操作)。

例如,在案例8中,有类似的东西:

 case '10':{
    //caching myObject once and then use it afterwards
    var myObject = $("#object"),
        $window = $(window);

    myObject.animate(
      {
      crSpline: $.crSpline.buildSequence([[4141, 820], [4568, 949], [4447, 1175]]) },
      {
      duration: 5000,
          step: function() {
            var mover = myObject, //no need to refetch the object               
            posX = mover.position().left;
            posY = mover.position().top;

            $window.scrollLeft(posX - $window.width() / 2)
            .scrollTop(posY - $window.height() / 2);
          }, 

          complete: function() {
            $.colorbox({href:"dialog-8.html", width:"737px", height:"434px", iframe: true, overlayClose: false, escKey: false, close: ""});
          }
      }
    );
}

ps:另外,我不确定您的应用程序的语义,但您可能需要添加自己的逻辑来跟踪posX和posY,因为它们总是可以引用原始缓存对象,但在所有情况下,请执行我提到的步骤,以确保选择器的成本是造成问题的原因(就像我的情况一样)。

答案 2 :(得分:2)

首先,您应优化代码,为动画创建一个函数(未经测试,但应该有效):

function animateMyObjet(duration,sequence,callback)
{
    $("#object").animate(
    {   crSpline: $.crSpline.buildSequence(sequence),
        {
          duration: duration,
          step: function() {
            var mover = $('#object'),               
            posX = mover.position().left;
            posY = mover.position().top;

            $(window)
            .scrollLeft(posX - $(window).width() / 2)
            .scrollTop(posY - $(window).height() / 2);
          },
          complete: function() {
            callback();
        }
    }
}

在你的代码中调用如下:

switch (sessionStorage.gameMainStage)
{
  case '1': animateMyObjet(10000,[[715, 425], [582, 524], [556, 646], [722, 688], [963, 629], [1143, 467]],                                                                                  
function() {
$.colorbox({href:"dialog-1.html", width:"737px", height:"474px", iframe: true, overlayClose: false, escKey: false, close: ""});
        break;

case '2' : ...

}

其次,几周前我发现网页元素的数量正在影响IE9的性能。尝试隐藏所有不需要的元素,例如由于可滚动容器而隐藏的元素。

有时,屏幕的可见元素数量也会影响动画效果。对于测试,尝试减少浏览器窗口大小并播放动画。我很确定动画会更流畅。

我希望这些建议可以帮到你。如果您发现问题,请不要忘记发布最终解决方案!

最后,查看有关IE9性能问题的潜在相关主题:IE9 : Always small CPU utilization on my web site

答案 3 :(得分:0)

您可以尝试检查以检查IE是否尝试以不同于IE9浏览器模式和IE9文档模式的方式工作,即怪癖或兼容模式。如果它确实试图强制它使用默认值。 Force IE compatibility mode off using tags

答案 4 :(得分:0)

我的想法是,如果你看到你的事件处理程序经常被调用,那么事件处理程序只是设置一个超时(比如说10毫秒),如果当前没有设置超时并且在超时函数中具有移动功能。