skip to Main Content

how do i make this traffic light count properly the duration ("duração"), after the first cicle, starts a visual glitch on the timer glitch

var sinal = setTimeout(red, 0)
function red() {
    let i = 0
    vermelho.style.backgroundColor = cores[0];
    amarelo.style.backgroundColor = cores_off[1];
    verde.style.backgroundColor = cores_off[2];
    setTimeout(yellow, 60000)
    var d1 = setInterval(function duração1() {
        i++
        cromonometro.innerHTML = `${i}`
    }, 1000)
}
function yellow() {
    let i = 0
    vermelho.style.backgroundColor = cores_off[0];
    amarelo.style.backgroundColor = cores[1];
    verde.style.backgroundColor = cores_off[2];
    setTimeout(green, 7000)
    var d2 = setInterval(function duração2() {
        i++
        cromonometro.innerHTML = `${i}`
    }, 1000)
}
function green() {
    let i = 0
    vermelho.style.backgroundColor = cores_off[0];
    amarelo.style.backgroundColor = cores_off[1];
    verde.style.backgroundColor = cores[2];
    setTimeout(red, 60000)
    var d3 = setInterval(function duração3() {
        i++
        cromonometro.innerHTML = `${i}`
    }, 1000)
}

i tried to use clear interval, but i don’t have the knowledge yet

2

Answers


  1. Make d1, d2, and d3 global variables. Then each function can clear the previous interval.

    var sinal = setTimeout(red, 0)
    let d1, d2, d3;
    
    function red() {
      clearInterval(d3);
      let i = 0
      vermelho.style.backgroundColor = cores[0];
      amarelo.style.backgroundColor = cores_off[1];
      verde.style.backgroundColor = cores_off[2];
      setTimeout(yellow, 60000)
      d1 = setInterval(function duração1() {
        i++
        cromonometro.innerHTML = `${i}`
      }, 1000)
    }
    
    function yellow() {
      clearInterval(d1);
      let i = 0
      vermelho.style.backgroundColor = cores_off[0];
      amarelo.style.backgroundColor = cores[1];
      verde.style.backgroundColor = cores_off[2];
      setTimeout(green, 7000)
      d2 = setInterval(function duração2() {
        i++
        cromonometro.innerHTML = `${i}`
      }, 1000)
    }
    
    function green() {
      clearInterval(d2);
      let i = 0
      vermelho.style.backgroundColor = cores_off[0];
      amarelo.style.backgroundColor = cores_off[1];
      verde.style.backgroundColor = cores[2];
      setTimeout(red, 60000)
      d3 = setInterval(function duração3() {
        i++
        cromonometro.innerHTML = `${i}`
      }, 1000)
    }

    BTW, your cycle is backwards. The normal order is green -> yellow -> red.

    Login or Signup to reply.
  2. There is a way of doing this that might be easier to follow. By using async/await you can write a function that ‘sleeps’ for a number of seconds, we can then use that function instead of calling setTimeout and setInterval.

    (Unfortunately there is no built in sleep function in JavaScript, but we can create one with a oneliner, basically we create a promise that will resolve after a number of ms that you choose when you call the sleep function. And since await is just one way of calling promises await sleep(milliseconds) then works fine inside an async function.)

    We create an array with the sequence and time each light should be on, easy to find and change since it is separate from the rest of the programming logic.

    Then we just loop through that array, turn the right light on, sleep for the duration specified in the array and turn the light off, moving on to the next part of the sequence in the next iteration of the loop, and so on…

    At the end of our function we call the function again (recursion) to repeat the sequence.

    async function trafficLight() {
      // a function that let us sleep/pause for a number of ms
      const sleep = ms => new Promise(res => setTimeout(res, ms));
      // get the div for each light
      const [red, yellow, green] =
        [...document.querySelectorAll('.traffic-light div')];
      // how many seconds should each light be on in a sequence
      const onForSeconds = [
        [red, 5],
        [yellow, 1],
        [green, 4],
        [yellow, 1]
      ];
      // run the sequence
      for (let [light, seconds] of onForSeconds) {
        light.classList.add('active');
        await sleep(seconds * 1000);
        light.classList.remove('active');
      }
      // call trafficLight again to repeat the sequence
      trafficLight();
    }
    
    trafficLight();
    .traffic-light {
      display: inline-block;
      background: black;
    }
    
    .traffic-light div {
      border-radius: 50%;
      width: 50px;
      height: 50px;
      margin: 10px;
      background-color: rgba(255, 255, 255, 0.3);
      transition: background-color 0.5s;
    }
    
    .red.active {
      background-color: red;
    }
    
    .yellow.active {
      background-color: yellow;
    }
    
    .green.active {
      background-color: green;
    }
    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Traffic-lights</title>
    </head>
    
    <body>
      <div class="traffic-light">
        <div class="red"></div>
        <div class="yellow"></div>
        <div class="green"></div>
      </div>
    </body>
    
    </html>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search