2016-08-04 2 views
1

Я пытаюсь запустить этот код, чтобы сделать слайд-шоу из 3 изображений, но он не работает должным образом. Слайд-шоу запускается один раз, но затем просто останавливается ...setTimeout функция не работает с петлей

Ниже приведены мои JavaScript, CSS и HTML, и если вы запустите фрагмент кода, вы увидите, что показ слайдов запускается один раз.

HTML в основном объявляет контейнер div со слайдами как divs с определенным фоновым изображением. (Для этого вопроса я изменил изображения на цвета, чтобы вы могли видеть слайд-шоу в действии)

CSS объявляет положение каждого из изображений слайд-шоу, когда оно находится на виду и когда оно скрыто.

JavaScript циклически проходит через слайды, давая каждому из них класс «скрытых», когда они должны выходить из поля зрения. В конце он возвращает первый слайд, удаляя все «скрытые» классы.

Я уверен, что проблема связана с JavaScript с помощью функции setTimeout, поскольку всякий раз, когда я запускаю функции в консоли, она отлично работает, но когда я пытаюсь автоматически их запускать в моем 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. Таким образом, вы планируете 300 таймеров в вашем цикле 'for', все в три раза. – jfriend00

+0

Поместите некоторые операторы console.log внутри ваших функций slideAtoB, и вы увидите, что все 100 операторов журналов вы получаете в одно и то же мгновение. – morgancodes

ответ

1

Я получил это, работая с этим: (Спасибо Yotam Salmon за ваш ответ, вот что помогло мне стоять, что я делал неправильно)

В основном я получил каждую функцию, чтобы установить тайм-аут и запустить следующий, затем я получил последний, чтобы запустить первый. все, что мне нужно было тогда, чтобы начать первый вручную, тогда он просто бежал навсегда.

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

u right @Josh, извините, я не видел вашего ответа –

4

Когда вы setTimeout() код не ждет тайм-аут, чтобы закончить. Это означает, что ваш цикл for выполняется 100 раз через 2 секунды, еще 100 раз через 4 секунды и еще 100 раз через 6 секунд.

Вместо этого вы можете повторно установить таймауты после окончания третьего кадра.

Пример простого цикла тайм-аутов:

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; 
} 

 Смежные вопросы

  • Нет связанных вопросов^_^