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>
我正在尝试 运行 此代码制作 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>