setTimeout 函数不适用于 for 循环

setTimeout function not working with for loop

我正在尝试 运行 此代码制作 3 张图片的幻灯片,但无法正常工作。幻灯片放映 运行 一次,然后就停止了...

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

HTML 基本上是声明一个容器 div,其中包含幻灯片 divs 和特定的背景图像。 (对于这个问题,我将图像更改为颜色,以便您可以看到正在运行的幻灯片)

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

JavaScript 循环播放幻灯片,当它们应该移出视野时,给每张幻灯片 class 或 "hidden"。最后,它通过删除所有 "hidden" classes 带回第一张幻灯片。

我很确定问题出在 JavaScript 的 setTimeout 函数中,因为每当我 运行 控制台中的函数都运行良好,但是当我尝试自动将它们设置为运行 在我的 JS 中它只有 运行 一次。

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

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

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

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

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

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

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

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

当您 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次

正如其他人所提到的,您的循环实际上什么都不做,因为 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();

不使用带有 CSS3 动画的 JS 也可以获得相同的效果(不完全相同的代码,您应该稍微玩一下时代和风格)

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

我得到了它的工作: (感谢 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{
 width:100%;
 height:50%;
 background-image:url("white-wall.png");
}

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

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

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

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

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

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