Setinterval calling function only once?

Asked

Viewed 235 times

1

I want the Divs to move -50px to the left every 03 seconds. I used setInterval but it only runs the function once.

setInterval(function(){ document.querySelector('.filho').classList.add("ativado");
 }, 3000);
<style>
    body{

padding: 0;
margin: 0;
}
    .pai{
border:solid 1px black;
display: flex;
justify-content: space-around;
}

    #divs1{
padding: 100px;
background: pink;
transition: .5s;

}    #divs2{
padding: 100px;
background: green;
transition: .5s;

}    #divs3{
padding: 100px;
background: red;
transition: .9s;

}
    .ativado{
margin-left: -50px;
}

</style>
<!DOCTYPE HTML>
<html>
 <head>
  <meta charset="UTF-8">
 </head>
<body>

  <div class="pai">

   <div class="filho" id="divs1"></div>
   <div class="filho" id="divs2"></div>
   <div class="filho" id="divs3"></div>

  </div>
</body>
</html>

4 answers

2

Setinterval calling function only once?

The function, in fact is being called correctly every 3 seconds. The problem is that your setInterval simply add the class ativado every time it runs every three seconds. This will not change the position after the first time, since the class has already been added in the previous run, making no difference in the following calls.

What you need to do is something to add more 50px at each execution.


I made an example for you to take as a basis:

const el = document.querySelector('#el')
let current = 0

const interval = setInterval(() => {
  // Define o valor de "margin-top" como o valor anterior mais 10.
  // Note que temos que adicionar "px" após o valor calculado.
  el.style.setProperty('margin-top', `${current += 10}px`)
  console.log(`Valor atual: ${current}px`)
  
  // Caso o valor seja maior que 500, pare o intervalo:
  if (current >= 150) {
    clearInterval(interval)
    console.log('Intervalo interrompido! Fim.')
  }
}, 500)
<div id="el">Olá!</div>


Final code:

That way, you basically need this:

const el = document.querySelector('.filho')
let current = 0

const interval = setInterval(() => {
  el.style.setProperty('margin-left', `${current -= 50}px`)
  
  // Caso o valor seja maior que 500, pare o intervalo.
  // Você pode remover essa parte se desejar.
  if (current >= 750) {
    clearInterval(interval)
    console.log('Intervalo interrompido! Fim.')
  }
}, 3000)
body {
  padding: 0;
  margin: 0;
}

.pai {
  border: solid 1px black;
  display: flex;
  justify-content: space-around;
}

#divs1 {
  padding: 100px;
  background: pink;
  transition: 0.5s;
}

#divs2 {
  padding: 100px;
  background: green;
  transition: 0.5s;
}

#divs3 {
  padding: 100px;
  background: red;
  transition: 0.9s;
}
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
  </head>
  <body>
    <div class="pai">
      <div class="filho" id="divs1"></div>
      <div class="filho" id="divs2"></div>
      <div class="filho" id="divs3"></div>
    </div>
  </body>
</html>

2

Actually the function is correct, I added a console.log inside setInterval, you can see that the log appears several times.

The problem is that Voce is simply adding a class in the element, the css effect is not incremental, can have the class ativado in the element as many times as you want and the margin-left will always be -50

what you need to do is increase the value.

var margin = 0
setInterval(function(){
  console.log('fui chamado')
  margin -= 50
  document.querySelector('.filho').style.marginLeft = margin+'px'
}, 3000);
<style>
    body{

padding: 0;
margin: 0;
}
    .pai{
border:solid 1px black;
display: flex;
justify-content: space-around;
}

    #divs1{
padding: 100px;
background: pink;
transition: .5s;

}    #divs2{
padding: 100px;
background: green;
transition: .5s;

}    #divs3{
padding: 100px;
background: red;
transition: .9s;

}
    .ativado{
margin-left: -50px;
}

</style>
<!DOCTYPE HTML>
<html>
 <head>
  <meta charset="UTF-8">
 </head>
<body>

  <div class="pai">

   <div class="filho" id="divs1"></div>
   <div class="filho" id="divs2"></div>
   <div class="filho" id="divs3"></div>

  </div>
</body>
</html>

2

Your problem is that at each interval you are setting the marginLeft to -50px, so it stands still after the other repetitions, you need to decrease this value at each interval.

var obj = document.getElementsByClassName("filho")[0];
var margin = parseInt(obj.style.margin-left, 10);
obj.style.marginLeft = (margin - 50) + "px";

Enter this in your setInterval, it should solve your problem.

2

The code is running what you asked it to do, adding a class to an element, but that doesn’t make the CSS styles accumulate, that is, two any elements, one with a class ativado and the other with two classes ativado are the same (has the same style).

What you need to do is increase the margin, for example:

setInterval(function(){
    const style = document.querySelector('.filho').style;
    style.marginLeft = `${Number.parseInt(style.marginLeft.replace('px', '')) - 50}px`
}, 3000);

Browser other questions tagged

You are not signed in. Login or sign up in order to post.