【问题标题】:Can I insert multiple setTimeouts in a setInterval?我可以在一个 setInterval 中插入多个 setTimeouts 吗?
【发布时间】:2017-11-20 08:07:42
【问题描述】:

我刚开始学习 JavaScript,现在我正在制作一个红色、绿色和橙色的虚拟红绿灯。我想通过在外部添加 setInterval 来创建一个循环。这是可能的还是我应该使用其他方法来制作循环。我尝试制作一个for(;;){} 但这会导致错误并且网页永远不会加载。这是我当前的代码。

var red = document.getElementById("circleRed");
var orange = document.getElementById('circleOrange')
var green = document.getElementById('circleGreens');
    
setInterval(
    
  setTimeout( function(){
    red.style.backgroundColor = "red";
  }, 2000),
    
   setTimeout(function(){
      green.style.backgroundColor = "green";
      red.style.backgroundColor = "black";
   }, 5000),
    
    setTimeout(function(){
      orange.style.backgroundColor = "orange";
      green.style.backgroundColor = "black";
    }, 10000),
    
    5000);
#circleRed, #circleGreens, #circleOrange {
    width: 50px;
    height: 50px;
    -webkit-border-radius: 25px;
    -moz-border-radius: 25px;
    border-radius: 25px;
    margin-bottom: 10px;
    background-color: "black";
}

.back {
    width: 60px;
    margin: 10px 0px 10px 20px;
    padding-left: 10px;
    padding-top: 10px;
    padding-bottom: 10px;
    background-color: black;
}
    
body{
    margin: 0;
}
<div class="back">
  <div id="circleRed">
  </div>
  <div id="circleOrange">
  </div>
  <div id="circleGreens">
  </div>
</div>

【问题讨论】:

    标签: javascript html settimeout setinterval


    【解决方案1】:

    您可以在 loop 函数中调用所有 setTimeout 函数。并用setInterval 调用这个循环函数。 注意:我还更改了代码中的一些颜色更改部分。

    jsfiddle 链接:https://jsfiddle.net/zgdx5xan/

    var red = document.getElementById("circleRed");
    var orange = document.getElementById('circleOrange')
    var green = document.getElementById('circleGreens');
    
    loop();
    setInterval(loop,11000);
    
    function loop(){
    	console.log("loop started")
      setTimeout( function(){
        red.style.backgroundColor = "red";
        orange.style.backgroundColor = "black";
        green.style.backgroundColor = "black";
        console.log("red opened")
      }, 2000);
    
       setTimeout(function(){
        green.style.backgroundColor = "green";
        red.style.backgroundColor = "black";
        console.log("green opened")
      }, 5000);
    
      setTimeout(function(){
        orange.style.backgroundColor = "orange";
        green.style.backgroundColor = "black";
        red.style.backgroundColor = "black";
        console.log("orange opened")    
      }, 10000);
    }
    #circleRed, #circleGreens, #circleOrange {
      width: 50px;
      height: 50px;
      -webkit-border-radius: 25px;
      -moz-border-radius: 25px;
      border-radius: 25px;
      margin-bottom: 10px;
      background-color: "black";
    }
    
    
    
    .back{
      width: 60px;
      margin: 10px 0px 10px 20px;
      padding-left: 10px;
      padding-top: 10px;
      padding-bottom: 10px;
      background-color: black;
    }
    
    body{
      margin: 0;
    }
     
       <div class="back">
        <div id="circleRed">
    
        </div>
        <div id="circleOrange">
    
        </div>
        <div id="circleGreens">
    
        </div>
      </div>
     

    【讨论】:

      【解决方案2】:

      setInterval 和 setTimeout 一样,也需要一个函数作为第一个参数传递,然后您就可以在该函数中编写您的 setTimeout。

      var red = document.getElementById("circleRed");
      var orange = document.getElementById('circleOrange');
      var green = document.getElementById('circleGreens');
      
      setInterval(function () {
        red.style.backgroundColor = "black";
        orange.style.backgroundColor = "black";
        green.style.backgroundColor = "black";
      
        setTimeout(function () {
          red.style.backgroundColor = "red";
        }, 2000);
      
        setTimeout(function () {
          green.style.backgroundColor = "green";
          red.style.backgroundColor = "black";
        }, 5000);
      
        setTimeout(function () {
          orange.style.backgroundColor = "orange";
          green.style.backgroundColor = "black";
        }, 8000);
      }, 10000)
      

      我已经稍微调整了你的时间,因为你的最终超时时间比间隔时间长。你可以在这里看到这个工作:codepen example

      【讨论】:

        【解决方案3】:

        将交通信号灯视为具有 3 种状态的对象,即 redOn、greenOn 和 OrangeOn。您需要遍历状态,因此从 redOn 开始传递序列中的下一个并在最后一个中重置。我认为这里的 setInterval 不是必需的,因为它会让您关心无关紧要的总时间。

        var red = document.getElementById("circleRed");
        var orange = document.getElementById('circleOrange')
        var green = document.getElementById('circleGreens');
        
        var redFor = 200 //2000
        var greenFor = 500 //5000
        var orangeFor = 1000 //10000
        
        let redOn = function(next) {
          red.style.backgroundColor = "red";
          orange.style.backgroundColor = "black";
          setTimeout(next, redFor);
        }
        
        let orangeOn = function(next) {
          orange.style.backgroundColor = "orange";
          green.style.backgroundColor = "black";
          setTimeout(next, orangeFor);
        }
        
        let greenOn = function(next) {
          green.style.backgroundColor = "green";
          red.style.backgroundColor = "black";
          setTimeout(next, greenFor);
        }
        
        let start = function() {
          redOn(function() {
            greenOn(function() {
              orangeOn(start)
            })
          })
        }
        
        start()
        #circleRed,
        #circleGreens,
        #circleOrange {
          width: 50px;
          height: 50px;
          -webkit-border-radius: 25px;
          -moz-border-radius: 25px;
          border-radius: 25px;
          margin-bottom: 10px;
          background-color: "black";
        }
        
        .back {
          width: 60px;
          margin: 10px 0px 10px 20px;
          padding-left: 10px;
          padding-top: 10px;
          padding-bottom: 10px;
          background-color: black;
        }
        
        body {
          margin: 0;
        }
        <html>
        
        <head>
          <link rel="stylesheet" type="text/css" href="object2.css">
          <meta charset="utf-8">
          <title></title>
        </head>
        
        <body>
          <div class="back">
            <div id="circleRed"></div>
            <div id="circleOrange"></div>
            <div id="circleGreens"></div>
          </div>
          <script src="objects1.js"></script>
        </body>
        
        </html>

        【讨论】:

          【解决方案4】:

          这是一个替代实现,每个灯的时间相等。

          var red    = document.getElementById('circleRed');
          var orange = document.getElementById('circleOrange');
          var green  = document.getElementById('circleGreens');
          
          /* Set an array with the desired order to turn on lights */
          var lights = [red, green, orange];
          
          function open(light) {
              light.classList.add('opened');
          }
          
          function close(light) {
              light.classList.remove('opened');
          }
          
          
          function change() {
              close(lights[i]);
              i = (i + 1) % lights.length;
              open(lights[i]);
          }
          
          /* Start */
          var i = 0;
          open(lights[i]);
          setInterval(change, 1000);
          .circle {
              width: 50px;
              height: 50px;
              border-radius: 25px;
              margin: 5px;
              opacity: 0.2;
              transition: opacity 200ms;
          }
          
          .circle.opened {
              opacity: 1;
          }
          
          #circleRed {
              background-color: red;
          }
          
          #circleOrange {
              background-color: orange;
          }
          
          #circleGreens {
              background-color: green;
          }
          
          
          .back {
              width: 60px;
              padding: 5px;
              background-color: black;
          }
          <div class="back">
            <div id="circleRed" class="circle"></div>
            <div id="circleOrange" class="circle"></div>
            <div id="circleGreens" class="circle"></div>
          </div>

          说明:

          不是将每个圆圈的背景颜色从黑色更改为自己的颜色以点亮圆圈,反之亦然以关闭,在我的示例中,所有圆圈都将其各自的颜色(红色、绿色或橙色)淡化为(几乎)使用opacity: 0.2 透明(最初我使用0,但我认为使用0.2 看起来更好)参见:opacity

          所以,所有具有.circle 类的元素都有:

          .circle {
              /* Other properties */
              opacity: 0.2;
          }
          

          然后,我使用一个名为 opened 的类将不透明度设置为 1,使圆圈可见。

          .circle.opened {
              opacity: 1;
          }
          

          由于.circle.opened 具有比.circle 更高的specificity,因此不透明度:1 优先于具有两个类(circleopened)的元素。

          要从灯项中添加或删除类opened,我使用两个简单的函数openclose 来操作元素的classList这很重要。一般来说,更推荐在类中定义元素的属性(样式),并使用JS添加或删除该类来改变元素,直接用JS修改元素的样式。

          所以,它更干净,更推荐这样做:

          /* CSS */
          .red { background-color: red }
          
          /* Javascript */
          var element = document.getElementById('#element_ID');
          element.classList.add('red');
          

          比:

          /* Javascript */
          var element = document.getElementById('#element_ID');
          element.style.backgroundColor = 'red';
          

          即使第二种方式看起来更容易。

          为了改变灯光,我按所需顺序制作了一个包含元素的数组:

          var lights = [red, green, orange];
          

          如您所见,灯光Array 的每个元素都是圆圈之一,我们已经使用document.getElementById() 存储在变量中(如果您不熟悉数组,请花一些时间阅读并理解它们它们是什么以及它们是如何工作的。它们是任何编程语言中最基本的数据结构之一,因此掌握它们很重要。)

          首先,我向0 (var i = 0) 启动一个全局变量,然后点亮第一盏灯:

          open(lights[i]);
          

          由于i 等于0,lights[i],所以lights[0]red(在JS 中,与大多数语言一样,数组从0 开始计数元素)。这样open(lights[i])就等于open(red)

          然后我执行setInterval(change, 1000),所以每秒都会调用函数change()。而这个change 函数有什么作用?

          基本上:

          // Turn off the current light
          close(lights[i]);
          
          // Increment i, so that lights[i] points to the next element... 
          i = (i + 1) % lights.length;
          
          // Turn on this next element
          open(lights[i]);
          

          这里最稀有的可能是增量。为什么我要i = (i + 1) % lights.length 而不是i++

          如果我在连续调用change 后执行i++i 将是:0、1、2、3、4、5、6... 所以,当我尝试访问 lights[i] 时,我'会报错,因为lights数组的第3、4、5...位置没有元素。

          我需要我的序列是:0, 1, 2, 0, 1, 2, 0, 1, 2...

          如何获得这个想要的序列而不是 0、1、2、3、4、5、6...?

          也许更容易理解的方式是:

          i++;
          if (i > 2) {
              i = 0;
          }
          

          但我使用Remainder 运算符(%)来达到相同的效果。

          我希望这会有所帮助!


          还有一个可以轻松配置每个灯的持续时间:

          var lights = {
              red: {
                  node: document.getElementById('circleRed'),
                  duration: 4000,
              },
              green: {
                  node: document.getElementById('circleGreens'),
                  duration: 2000,
              },
              orange: {
                  node: document.getElementById('circleOrange'),
                  duration: 800,
              }
          };
          
          var order = ['red', 'green', 'orange'];
          
          
          function open(light) {
              light.node.classList.add('opened');
          }
          
          function close(light) {
              light.node.classList.remove('opened');
          }
          
          function change() {
              close(lights[order[i]]);
              i = (i + 1) % order.length;
              open(lights[order[i]]);
              setTimeout(change, lights[order[i]].duration);
          }
          
          /* Start */
          var i = 0;
          open(lights[order[i]]);
          
          setTimeout(change, lights[order[i]].duration);
          .circle {
              width: 50px;
              height: 50px;
              border-radius: 25px;
              margin: 5px;
              opacity: 0;
              transition: opacity 200ms;
          }
          
          .circle.opened {
              opacity: 1;
          }
          
          #circleRed {
              background-color: red;
          }
          
          #circleOrange {
              background-color: orange;
          }
          
          #circleGreens {
              background-color: green;
          }
          
          
          .back {
              width: 60px;
              padding: 5px;
              background-color: black;
          }
          <div class="back">
            <div id="circleRed" class="circle"></div>
            <div id="circleOrange" class="circle"></div>
            <div id="circleGreens" class="circle"></div>
          </div>

          【讨论】:

          • 非常感谢您的回答,但我还不熟悉您使用的大部分语法。我一直在寻找更简单的方法。
          • 不客气,丹尼。我将尝试在我的第一个示例(最简单的示例)中添加更多 cmets 以帮助您理解它。我认为这是一个很好的,因为它使用了一些重要的 JS 基本元素。 :)
          • 嘿@DannyArcher,我为我的第一个算法添加了更好的解释。我希望它会有所帮助。
          【解决方案5】:

          将所有setTimeout( function(){}) 放在一个函数中,然后它就可以工作了

          注意:要使setInterval正常工作,毫秒必须至少是setTimeout函数的总和。

          red 出现时,您也忘记将orange 设置为黑色。

          var red = document.getElementById("circleRed");
          var orange = document.getElementById('circleOrange')
          var green = document.getElementById('circleGreens');
              
          setInterval(function(){ myTimer() }, 17000);
              function myTimer() {
            setTimeout( function(){
              red.style.backgroundColor = "red";
              orange.style.backgroundColor = "black";
            }, 2000),
              
             setTimeout(function(){
                green.style.backgroundColor = "green";
                red.style.backgroundColor = "black";
             }, 5000),
              
              setTimeout(function(){
                orange.style.backgroundColor = "orange";
                green.style.backgroundColor = "black";
              }, 10000)
              }
              myTimer();
          #circleRed, #circleGreens, #circleOrange {
              width: 50px;
              height: 50px;
              -webkit-border-radius: 25px;
              -moz-border-radius: 25px;
              border-radius: 25px;
              margin-bottom: 10px;
              background-color: "black";
          }
          
          .back {
              width: 60px;
              margin: 10px 0px 10px 20px;
              padding-left: 10px;
              padding-top: 10px;
              padding-bottom: 10px;
              background-color: black;
          }
              
          body{
              margin: 0;
          }
          <div class="back">
            <div id="circleRed">
            </div>
            <div id="circleOrange">
            </div>
            <div id="circleGreens">
            </div>
          </div>

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-07-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-08-10
            相关资源
            最近更新 更多