2012-10-19 33 views
6

我对下面的脚本有严重的视觉&性能问题。最大的问题是该对象的动画变得非常干,在IE9中几乎变得残缺不全,但在Firefox中越来越讨厌。可怜的JS/jQuery性能,尤其是在IE9和Firefox中

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

脚本(这是一个更大的集***的片段):

  1. 检查用户进程的HTML5会话存储日志通过 游戏。
  2. 根据舞台情况,使用crSpline在两个 点之间动画显示一个对象。
  3. 确保浏览器窗口沿着穿过一个大帆布对象 ,通过scrollLeft等
  4. 最后,通过colorbox加载一个弹出窗口。
  5. 当此框关闭时,用户进度日志会相应增加,对象再次移动。

有没有很明显的速度改进,我可以做我的代码?有一点点的回应,我该如何减少呢?有没有我失踪的无限循环?我可以使用软件来分析JS的慢点吗?

***(我不能提供其他的JS文件或HTML,但我已经确定这个脚本的问题)


UPDATE: 更公平一点测试完成后,似乎步骤动画函数 - 它通过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); 
+0

只是一个侧面说明从基准测试页面:'这个基准测试的核心JavaScript语言而已,而不是DOM或其​​他浏览器APIs' - 你的颜色框和动画都几乎纯粹是DOM。 –

回答

5

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

我注意到的第一件事情是,在IE(版本8具体)中,附加到window.scroll或.resize的回调似乎在调整窗口大小时比Chrome或FF触发多了很多次(或滚动)。因此,任何附加回调都会比Chrome更多地被称为增加其相对成本。

我们设法通过最小化这些回调内所做的最小操作来解决我们的问题,而我们获得的主要收获是摆脱了jQuery选择器。所以在你的情况下,例如var回调函数中的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和波西,因为他们总能引用原单缓存的对象,但在所有的情况下,做我所提到的,以确保选择的代价是什么导致了问题的步骤(因为它是在我的情况)。

11

恐怕你使用的图书馆太老了,不能期待出色的表演。

我没有看到你的代码什么不对(除了你可以使用一个功能与每个开关情况下,配置参数,但是这只是一个重构的事情不会影响性能显著)

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/

为你的工作干杯!

+0

CSS 2D变换不保证是硬件加速的。为了确保你获得硬件加速,你应该使用translate3d(0,0,0),它告诉浏览器你要使用Z轴(并且将在GPU中启动)。您仍然可以使用顶部和左侧并获得硬件加速。 http://www.html5rocks.com/en/tutorials/speed/html5/ – skyline3000

+1

真 - translate3d是硬件加速,并导致巨大的性能提升,但调用它们的元素太多太频繁将刚吃的加速资源。 2D变换通常不会加速,但他们仍然大大提高性能,因为改变它们的值不会导致DOM重新计算和重新渲染 - 这是与动画最大的性能猪。 – nxtwrld

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

+0

相关主题上的链接到Web开发人员工具栏中的Javascript分析非常有用,谢谢。 –

0

我的想法是,如果你看到你的事件处理程序过于频繁地被调用,那么事件处理程序只需设置一个超时(假设为10毫秒),如果没有超时被设置并且在超时功能中具有运动的内容。

相关问题