6

下面的脚本存在严重的视觉和性能问题。最大的问题是对象的动画变得非常生涩,在 IE9 中几乎是严重的,但在 Firefox 中却越来越烦人。

直到最近它一直非常快 - 但我担心复杂性会减慢速度。奇怪的是,Sunspider 基准测试在我的 IE9 实例中比在 Firefox 中运行得更快。

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

  1. 检查用户在游戏中的进度的 HTML5 会话存储日志。
  2. 根据舞台,使用crSpline为两点之间的对象设置动画。
  3. 通过 scrollLeft 等确保浏览器窗口在大画布上跟随对象。
  4. 最后,它通过colorbox加载一个弹出窗口。
  5. 当此框关闭时,用户进度日志会相应增加,并且对象会再次移动。

我可以对我的代码进行明显的速度改进吗?有相当多的重复,我怎样才能减少呢?是否有我遗漏的无限循环运行?有没有可以用来分析 JS 慢点的软件?

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


更新: 经过更多测试后,似乎 step animate 函数 - 通过 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);
4

5 回答 5

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/

为你的工作干杯!

于 2012-10-21T19:45:54.887 回答
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 因为它们可能总是引用原始缓存对象,但在所有情况下,请执行我提到的步骤确保选择器的成本是导致问题的原因(就像我的情况一样)。

于 2012-10-26T21:10:52.253 回答
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:我的网站上的 CPU 使用率总是很小

于 2012-10-21T19:50:11.910 回答
0

您可以尝试检查 IE 是否不会尝试在与 IE9 浏览器模式和 IE9 文档模式(即怪癖或兼容模式)不同的模式下工作。如果它确实试图强制它使用默认值。使用标签强制关闭 IE 兼容模式

于 2012-10-19T16:08:14.653 回答
0

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

于 2012-10-27T22:09:06.547 回答