这段代码应该一次更改五个图像。我不会详细介绍,但它必须使用一个数组来控制图像。问题是,在图像更改之间没有延迟。我已经研究过其他人在setTimeout中遇到的问题,但没有发现我做错了这一部分。
我知道可能有更简洁的方法可以做到这一点,但我试图使用易于解释的代码块来保持它的简单性。
<html lang="en">
<head>
<script>
var array=[0,0,0,0,0];
function updatelights() {
if (array[0]==1) {
document.images.light1.src="lighton.png";
}
else {
document.images.light1.src="lightoff.png";
}
if (array[1]==1) {
document.images.light2.src="lighton.png";
}
else {
document.images.light2.src="lightoff.png";
}
//other if statements here as above
}
function animatelights() {
light1on();
setTimeout(updatelights,1000);
light2on();
setTimeout(updatelights,1000);
light3on();
setTimeout(updatelights,1000);
light4on();
setTimeout(updatelights,1000);
light5on();
setTimeout(updatelights,1000);
}
function light1on() {
array=[1,0,0,0,0];
}
function light2on() {
array=[0,1,0,0,0];
}
function light3on() {
array=[0,0,1,0,0];
}
function light4on() {
array=[0,0,0,1,0];
}
function light5on() {
array=[0,0,0,0,1];
}
</script>
</head>
<body>
<!-- This is an HTML table with five columns. There is an image in each column-->
<table style="width:100%">
<tr>
<td><img name="light1" src="lightoff.png"></td>
<td><img name="light2" src="lightoff.png"></td>
<td><img name="light3" src="lightoff.png"></td>
<td><img name="light4" src="lightoff.png"></td>
<td><img name="light5" src="lightoff.png"></td>
</tr>
</table>
<!-- This is an HTML button -->
<button type = "button" onclick="animatelights()"> Animate </button>
</body>
</html>
当我看到这个时:
light1on();
setTimeout(updatelights,1000);
light2on();
setTimeout(updatelights,1000);
light3on();
setTimeout(updatelights,1000);
light4on();
setTimeout(updatelights,1000);
light5on();
setTimeout(updatelights,1000);
看起来你希望事情一行一行地进行,事实确实如此,但代码并没有按照这个顺序执行。setTimeout是非阻塞的,这意味着该代码的实际顺序是:
light1on();
light2on();
light3on();
light4on();
light5on();
然后一秒钟后,所有的更新灯都被调用:
updatelights(); //from setTimeout
updatelights(); //from setTimeout
updatelights(); //from setTimeout
updatelights(); //from setTimeout
updatelights(); //from setTimeout
所以解决方案应该是这样的:
var arr = [light1on, light2on, light3on, light4on, light5on];
var i = 1;
arr[0]();
var si = setInterval(function(){
if(i >= arr.length){
clearInterval(si);
}
arr[i]();
i++
updatelights();
}, 1000);
setTimeout
不是睡眠函数。
它将您传递给它的函数放入队列中,以便稍后调用:
- 指定的时间已过并且
- JS事件循环不忙于运行另一个函数
您将一个接一个地调用每个lightNon
函数,然后在大约一秒钟后,调用updatelights
5次。
解决这一问题的一般方法是:
- 用函数数组替换
lightNon
函数(或者,更好的是,使用数据数组的函数) - 创建一个变量来跟踪下一步要处理的数组的哪个索引
- 使用
setInterval
每秒运行一个函数,该函数:- 设置数组
- 调用更新函数
- 递增跟踪索引的变量
您有很多不必要的代码。如果我试图从你的例子中学习这些东西,我会完全困惑的。我冒昧地简化了你的例子。
这是一个JS Fiddle
HTML(我为图像添加了一个类名)
<table style="width:100%">
<tr>
<td><img class='rotateImage' name="light1" src="http://antigonishoptical.ca/images/black-dot.png"></td>
<td><img class='rotateImage' name="light2" src="http://antigonishoptical.ca/images/black-dot.png"></td>
<td><img class='rotateImage' name="light3" src="http://antigonishoptical.ca/images/black-dot.png"></td>
<td><img class='rotateImage' name="light4" src="http://antigonishoptical.ca/images/black-dot.png"></td>
<td><img class='rotateImage' name="light5" src="http://antigonishoptical.ca/images/black-dot.png"></td>
</tr>
</table>
<!-- This is an HTML button -->
<button type = "button" onclick="animatelights()"> Animate </button>
还有JS
// URL for the on light
var lightsOn = "http://info.sonicretro.org/images/1/1b/Reddot.gif";
// URL for the off light
var lightsOff = "http://antigonishoptical.ca/images/black-dot.png";
// The active light (you don't need an array since you only have one light on at a time)
var activeLight = 0;
function animatelights() {
// Get an array of your images by adding a class name to them
var lights = document.getElementsByClassName('rotateImage');
// Loop thru the image and turn all the lights off
for(var i=0; i<lights.length; i++) lights[i].src = lightsOff;
// Then turn on the light that is currently active
lights[activeLight].src = lightsOn;
// increment the active light variable so the next light lights up next time
activeLight++;
// Check to see if we've gone through all inputs. If we have the cirrent index won't exists,
// so we reset it back to zero
if('undefined' === typeof lights[activeLight]) activeLight = 0;
// After three seconds, call the function again recursively
setTimeout(animatelights, 3000);
}
这是错误的做法。
setTimeout()
不暂停或停止执行。它在给定的时间后执行一些代码。您可以使用回调函数来阻止执行这样的事情:
function second()
{
alert("ok");
}
setTimeout(second,100);
function secondFunction() {
alert("after 1 second");
}
setTimeout(secondFunction, 1000);
问题是因为您要同时更改array
。
您想在延迟(setTimeout
)后调用light2on
(etc)。正确的方法是在setTimeout
回调函数中调用它。您必须在updatelights
之前调用light[number]on
。对每一个都这样做:
setTimeout(function(){light2on();updatelights()},1000)
但是间隔会更快,并且不需要创建这些函数和全局变量。