2016-08-04 87 views
1

我试图运行此代码,使幻灯片的3个图像,但它不能正常工作。幻灯片放映只运行一次,但随后停止...setTimeout函数不适用于循环

以下是我的JavaScript,CSS和HTML,如果您运行代码片段,您将看到幻灯片放映运行一次。

HTML基本上是声明一个容器div与幻灯片divs wth特定的背景图像。 (对于此问题,我将图像更改为颜色,以便您可以看到幻灯片的实际使用情况)

CSS声明幻灯片的每个图像在普通视图和隐藏时的位置。

JavaScript在幻灯片中循环,当每个幻灯片应该移出视图时,每个幻灯片都会有一类“隐藏”。最后,它通过删除所有“隐藏”类来带回第一张幻灯片。

我很确定问题出在带有setTimeout函数的JavaScript中,因为每当我在控制台中运行它的功能时,它都能正常工作,但是当我尝试自动设置它们在我的JS中运行时,它只运行一次。

function slide1to2(){ 
 
\t document.getElementById('slide1').className = "hidden"; 
 
\t clearTimeout(s1to2); 
 
} 
 
function slide2to3(){ 
 
\t document.getElementById('slide2').className = "hidden"; 
 
\t clearTimeout(s2to3); 
 
} 
 
function slide3to1(){ 
 
\t document.getElementById('slide1').className = ""; 
 
\t document.getElementById('slide2').className = ""; 
 
\t clearTimeout(s3to1); 
 
} 
 

 
for(i=0; i<100; i++){ 
 
\t s1to2 = window.setTimeout(slide1to2, 2000); 
 
\t s2to3 = window.setTimeout(slide2to3, 4000); 
 
\t s3to1 = window.setTimeout(slide3to1, 6000); 
 
}
div#slideshow{ 
 
\t width:100%; 
 
\t height:50%; 
 
\t background-image:url("white-wall.png"); 
 
} 
 

 
div#slideshow div{ 
 
\t width:100%; 
 
\t height:inherit; 
 
\t background-repeat:no-repeat; 
 
\t background-position:center; 
 
\t background-color:rgba(0,0,0,0.5); 
 
\t position:absolute; 
 
\t transition:1s; 
 
} 
 

 
div#slideshow div[id$="1"]{ 
 
\t background:#FF8888; 
 
\t transform:translateX(0%); 
 
\t z-index:3; 
 
} 
 

 
div#slideshow div[id$="2"]{ 
 
\t background:#88FF88; 
 
\t transform:translateX(0%); 
 
\t z-index:2; 
 
} 
 

 
div#slideshow div[id$="3"]{ 
 
\t background:#8888FF; 
 
\t transform:translateX(0%); 
 
\t z-index:1; 
 
} 
 

 
div#slideshow div[id$="1"].hidden{ 
 
\t transform:translateX(-100%); 
 
} 
 

 
div#slideshow div[id$="2"].hidden{ 
 
\t transform:translateX(-100%); 
 
}
<div id="slideshow"> 
 
\t <div id="slide1"></div> 
 
\t <div id="slide2"></div> 
 
\t <div id="slide3"></div> 
 
</div>

+0

'的setTimeout()'是异步的。它不会阻止执行,直到计时器触发。相反,它只是为将来的某个时间安排一个计时器,并继续执行您的JavaScript。所以你在3个不同的时间安排了300个定时器。 – jfriend00

+0

在slideAtoB函数中加入一些console.log语句,您会看到在同一时刻所有日志语句都会得到。 – morgancodes

回答

1

我得到了它这方面的工作: (感谢Yotam鲑鱼的回答,那是在什么样的帮助我站在我做错了什么)

我基本上得到每个函数来设置超时并运行下面的一个,然后我得到最后一个再次运行第一个。我所需要的只是手动启动第一个,然后就是永远运行。

function slide1to2(){ 
 
    document.getElementById('slide1').className = "hidden"; 
 
    setTimeout(slide2to3, 4000); 
 
} 
 
function slide2to3(){ 
 
    document.getElementById('slide2').className = "hidden"; 
 
    setTimeout(slide3to1, 4000); 
 
} 
 
function slide3to1(){ 
 
    document.getElementById('slide1').className = ""; 
 
    document.getElementById('slide2').className = ""; 
 
    setTimeout(slide1to2, 4000); 
 
} 
 

 
slide1to2();
div#slideshow{ 
 
\t width:100%; 
 
\t height:50%; 
 
\t background-image:url("white-wall.png"); 
 
} 
 

 
div#slideshow div{ 
 
\t width:100%; 
 
\t height:inherit; 
 
\t background-repeat:no-repeat; 
 
\t background-position:center; 
 
\t background-color:rgba(0,0,0,0.5); 
 
\t position:absolute; 
 
\t transition:1s; 
 
} 
 

 
div#slideshow div[id$="1"]{ 
 
\t background:#FF8888; 
 
\t transform:translateX(0%); 
 
\t z-index:3; 
 
} 
 

 
div#slideshow div[id$="2"]{ 
 
\t background:#88FF88; 
 
\t transform:translateX(0%); 
 
\t z-index:2; 
 
} 
 

 
div#slideshow div[id$="3"]{ 
 
\t background:#8888FF; 
 
\t transform:translateX(0%); 
 
\t z-index:1; 
 
} 
 

 
div#slideshow div[id$="1"].hidden{ 
 
\t transform:translateX(-100%); 
 
} 
 

 
div#slideshow div[id$="2"].hidden{ 
 
\t transform:translateX(-100%); 
 
}
<div id="slideshow"> 
 
    <div id="slide1"></div> 
 
    <div id="slide2"></div> 
 
    <div id="slide3"></div> 
 
</div>

+0

你是否意识到这几乎就是我发布的内容?然而,你没有把它标记为公认的答案? – Josh

+1

你对@Josh,对不起,我没有看到你的答案 –

4

当你setTimeout(),代码不等待超时完成。这意味着您的for循环在2秒后执行100次,在4秒后执行另外100次,在6秒后执行另外100次。

取而代之,您可以在第三帧完成后重新设置超时。

与超时简单循环的例子:

var i = 0; 
function a() { 
    //Do some stuff 
    if (i++ < 100) setTimeout(a, 1000); 
} 

这^好。一个不好的例子是:

for (var i = 0; i < 100; i++) { 
    setTimeout(function() { 
     //Do stuff 
    }, 1000); 
} 

第一次将执行100次,间隔1秒,后者将执行1次。

0

正如其他人所说,你的循环无效,因为setTimeout是异步的。

实现所需结果的一种方法是在每个函数中设置回调函数。然后设置另一个函数来清除超时。要永久循环,只需删除stopTransitions函数及其调用者。

https://jsfiddle.net/24aLyg5v/

var timeout1, timeout2; 

function slide1to2(){ 
    document.getElementById('slide1').className = "hidden"; 
    document.getElementById('slide2').className = ""; 
    timeout1 = window.setTimeout(slide2to1, 2500); 
} 

function slide2to1(){ 
    document.getElementById('slide2').className = "hidden"; 
    document.getElementById('slide1').className = ""; 
    timeout2 = window.setTimeout(slide1to2, 2500); 
} 

function stopTransitions() { 
    clearTimeout(timeout1); 
    clearTimeout(timeout2); 
} 

window.setTimeout(stopTransitions, 20000); 
slide1to2(); 
1

你可以得到相同的效果,而无需使用JS用CSS3动画(不完全一样的代码,你应该随着时代和风格发挥一点点)

https://plnkr.co/edit/2AtRK7z9OJhs4AwX82rx?p=preview

.animation--slideshowAnimation { 
    width: 100%; 
    height: 500px; 
    background-size: cover; 
    background-position: 50%; 
    background-repeat: no-repeat; 

    animation-duration: 12s; 
    animation-name: slideshowAnimation; 
    animation-delay: 0; 
    animation-iteration-count: infinite; 
    animation-direction: forward; 
}