for循环中的SetTimeout

时间:2016-10-13 16:37:33

标签: javascript jquery for-loop settimeout

我试图编写一个更改3个图像的z-index的脚本。基本上,脚本应该以当前图像为目标并在下一个图像上应用更高的z-index,就像一种轮播,但是使用z-index而不是活动类。挑战是在特定间隔后设置z指数。问题是显示第一个图像,然后显示最后一个图像。这是我的代码:

HTML:

<div class="changingimages">
    <img src="#" data-time="3000" width="100%" class="alternateimage alternateimage1">
    <img src="#" data-time="2000" width="100%" class="alternateimage alternateimage2">
    <img src="#" data-time="4000" width="100%" class="alternateimage alternateimage3">
</div>

jQuery脚本

<script type="text/javascript">

jQuery(document).ready(function(){

    var changeImg = function(i, time, currentImg) {

        setTimeout(function(){

            jQuery(currentImg).next().css("z-index", i);

        }, time);
    };

    var numberOfChilds = jQuery(".changingimages").children().length;
    var currentIndexClass;
    var currentImg;
    var time;

    for (var i=1; i<=numberOfChilds; i++) {

            currentIndexClass = '.alternateimage' + i;
            currentImg = jQuery(currentIndexClass);
            time = jQuery(currentIndexClass).attr("data-time");

            changeImg(i, time, currentImg);

    }

});

我认为循环中的闭包存在一些问题,但不确定!

2 个答案:

答案 0 :(得分:3)

一种常见的误解是setTimeout计划相对于先前排队的事件运行的事件。从理论上讲,您似乎相信以下内容:

setTimeout(f, 100);
setTimeout(g, 100);
setTimeout(h, 100);

会产生如下的时间表:

0ms   Start
100ms Run f()
200ms Run g()
300ms Run h()

现实情况是setTimeout中的时间选项意味着&#34;至少在这么多时间过后才运行此功能。&#34;离开上一个例子,你实际上会得到更像

的东西
0ms   Start
100ms Run f()
101ms Run g()
102ms Run h()

要正确分隔代码,请继续添加超时时间而不是替换它。

var time = 0;

for (var i = 1; i <= numberOfChilds; i++) {
  currentIndexClass = '.alternateimage' + i;
  currentImg = jQuery(currentIndexClass);

  // Add to the previous time
  time += parseInt(jQuery(currentIndexClass).attr("data-time"), 10);
  changeImg(i, time, currentImg);
}

答案 1 :(得分:0)

这是一个实现使用超时来实现你想要的小提琴。

fiddle

.textArea {
  position: absolute;
  height: 50px;
  width: 50px;
  display: block;
}

.box_a {
  background-color: blue;
}

.box_b {
  background-color: red;
}

.box_c {
  background-color: orange;
}

.active {
  z-index: 3;
}


<div class="textArea box_a active">a</div>
<div class="textArea box_b">b</div>
<div class="textArea box_c">c</div>

$(function(){
  var $elem = $('.textArea');

  timeout(0);

  function timeout(i){
    $($elem[i]).addClass('active');
    return setTimeout(function(){
      $elem.removeClass('active');
      i++;
      if(i >= $elem.length){
        i = 0
      }
      timeout(i);
    }, 1000)
  }
});

请注意,它不使用for循环,因为timeout是异步的,不会按顺序执行。每个超时基本上会同时触发,然后根据等待时间执行操作。

解决方案是创建一个跟踪索引的函数,以及上次超时何时完成执行。