我正在创建一个游戏,其中灯光围绕圆圈运行,你必须尝试连续三次在同一地点停止灯光。目前,我正在使用以下代码循环灯光并将它们“打开”和“关闭”:
var num_lights = 20;
var loop_speed = 55;
var light_index = 0;
var prevent_stop = false; //If true, prevents user from stopping light
var loop = setTimeout(startLoop, loop_speed);
function startLoop() {
prevent_stop = false;
$(".light:eq(" + light_index + ")").css("background-color", "#fff");
light_index++;
if(light_index >= num_lights) {
light_index = 0;
}
$(".light:eq(" + light_index + ")").css("background-color", "red");
loop = setTimeout(startLoop, loop_speed);
}
function stopLoop() {
clearTimeout(loop);
}
在大多数情况下,代码似乎运行得很好,但如果我在另一个标签中同时运行视频,那么灯的打开和关闭似乎有点突然。关于我如何可能加快速度的任何输入都会很棒。
有关上述代码的示例,请查看此页面:http://ericditmer.com/wheel
答案 0 :(得分:2)
当优化要首先看的东西时,不要做两次你只需要做一次。从DOM中查找元素可能很昂贵,你肯定知道你想要哪些元素,那么为什么不预先获取所有元素并且多次无效呢?
我的意思是你应该
var lights = $('.light');
这样你以后可以说
lights.eq(light_index).css("background-color", "red");
请确保在第二件事情中保留lights
的范围。
编辑:每条评论更新。
答案 1 :(得分:2)
我会创建一个选择器引用的全局数组,因此每次调用函数时都不必执行它们的选择器。我还会考虑交换类名,而不是属性。
以下是jQuery性能的一些信息:
http://www.componenthouse.com/article-19
编辑:那篇文章虽然很老,但jQuery已经发展了很多。这是最近的:http://blog.dynatrace.com/2009/11/09/101-on-jquery-selector-performance/
答案 2 :(得分:1)
我要注意的一件事是你使用了setTimeout()
并且真正设计它的行为就像setInterval()
。
请尝试使用setInterval()
。我不是js引擎大师,但是我想认为setTimeout的不断重用必须对使用setInterval()
(你只需要设置一次)所不具备的性能产生一些影响。
编辑:
Diodeus的Curtousy,一个支持我发言的相关帖子:
答案 3 :(得分:1)
您可以尝试将灯元素存储在数组中,而不是每次都使用选择器。类选择器可能有点慢。
var elements = $('.light');
function startLoop() {
prevent_stop = false;
$(elements[light_index]).css('background-color', '#fff');
...
}
这假设元素已经在DOM中按预期顺序排列。
答案 4 :(得分:0)
好的,这包括一些“最佳实践”改进,如果它真的优化了应该测试的执行速度。至少你可以宣称你现在正在编写忍者风格 lol
// create a helper function that lend the array reverse function to reverse the
// order of a jquery sets. It's an object by default, not an array, so using it
// directly would fail
$.fn.reverse = Array.prototype.reverse;
var loop,
loop_speed = 55,
prevent_stop = false,
// prefetch a jquery set of all lights and reverses it to keep the right
// order when iterating backwards (small performance optimization)
lights = $('.light').reverse();
// this named function executes as soon as it's initialized
// I wrapped everything into a second function, so the variable prevent_stop is
// only set once at the beginning of the loop
(function startLoop() {
// keep variables always in the scope they are needed
// changed the iteration to count down, because checking for 0 is faster.
var num_lights = light_index = lights.length - 1;
prevent_stop = false;
// This is an auto-executing, self-referencing function
// which avoids the 55ms delay when starting the loop
loop = setInterval((function() {
// work with css-class changing rather than css manipulation
lights.eq( light_index ).removeClass('active');
// if not 0 iterate else set to num_lights
light_index = (light_index)? --light_index:num_lights;
lights.eq( light_index ).addClass('active');
// returns a referenze to this function so it can be executed by setInterval()
return arguments.callee;
})(), loop_speed);
})();
function stopLoop() {
clearInterval(loop);
}
干杯neutronenstern