2016-08-04 63 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; 
}