Time for transitions to be ready for execution

Asked

Viewed 32 times

0

The problem is that when I assign a transition to an already "painted" element in the DOM, it is not yet ready to perform in the following statement.

I will illustrate:

Suppose I have the "cheer" class and in that class there’s a transition.

.animar {
    transition: all 1s;
}

If I assign this class dynamically to a DOM element, using Javascript, and you want to use the transition in the following statement, I can’t do it. Would that be:

var elemento = document.querySelector('#qualquercoisa');

// Atribuo a classe que contem a transição
elemento.classList.add('animar');

// Modifico o CSS do elemento, mas ele não é animado. O elemento é movido direto, sem nenhuma transição. 
elemento.style.marginLeft = '300px';

The way it works:

For the transition to run, as expected, I have to do so:

 // Continuação do código acima
 setTimeout(function() {
   elemento.style.marginLeft = '600px';
 }, 10);

That is to say: the transition is only executed if I give a time after assigning the class, and then set the style modifications I want. It would be a kind of "time for the browser to process".

I was stunned by this, because how will I know how long it takes for the browser to be ready to run an animation on that element? There’s no way this is the most appropriate way to do this. Could someone point out some solution? Or better: the right way, because I got into this alone and I’m pretty sure it’s wrong... = P

Thank you.

  • Why don’t you just have it 300px in the CSS, and then animate to 600px?

  • @Sergio I don’t think you understand the problem. From 0 to 300 is where the bug is, it’s where the element is not animated. I just switched to 600 to illustrate that, after the setTimeout, the element is normally animated from 300 to 600.

  • @Sergio There was also an error in the code comment. It was supposed to be "It’s NOT animated". I fixed.

  • "From 0 to 300 is where the bug is" - Okay, but you have in CSS some initial value for margin-left (in the CSS)?

  • @Sergio Não. The value is the default; 0px.

  • @And this is not a "real code", it’s just an illustration of a problem I’ve had for some time.

  • You have to start in CSS, the starting value is not 0 is "undefined"

  • @Sergio I will analyze it better, because I have this problem in local files, but Jsfiddle ran, with and without setting an initial value. https://jsfiddle.net/zjnk1usk/

  • Okay, if you can reproduce the problem in jsFiddle it tells me to take a look too.

  • @Sergio In fact the whole problem is the same. I made the same code locally and it didn’t work. The div already appears at position 300px. NOTE: As it is only Front-end, it is not in localhost; it is direct link to the file.

  • And if you value your project initially, it doesn’t work?

  • @Sergio No. I tried.

  • Test, before using Javascript do console.log(window.getComputedStyle(elemento).marginLeft);. What gives?

  • @Sergio Dá "0px". But check it out: just put this instruction between the querySelecor and the style.marginLeft, the animation ran.

  • Okay, I was convinced that the browser did not set the 0px as a starting value. If this happens then the problem is that the browser is "spared" in the waiting repaint before adding the class to do various things at the same time. You can’t put that class together from scratch?

  • @Sergio No, because I need to switch between animate and not animate when Seto different positions for the element. But the setTimeout "solution" seems to work. Thank you for your attention. Good evening.

  • Yes setTimeout is a valid way. another variant would be to change the style.transitionDuration to zero and then replace.

Show 12 more comments

1 answer

0

To check when the animation is finished, add addEventListener to the element that will call a callback:

var div = document.querySelector('#div')
div.classList.add('animar');
div.style.marginLeft = '300px';
div.addEventListener("webkitTransitionEnd", callBack,false);
div.addEventListener("transitionend", callBack,false);
div.addEventListener("otransitionend", callBack,false);

window.onload = function(){
	var div = document.querySelector('#div')
	div.classList.add('animar');
	div.style.marginLeft = '300px';
	div.addEventListener("webkitTransitionEnd", callBack,false);
	div.addEventListener("transitionend", callBack,false);
	div.addEventListener("otransitionend", callBack,false);
}

function callBack(){
	alert("Fim");
}
.animar {
    transition: all 1s;
}

#div {
	width: 30px;
	height: 30px;
	background: red;
  }
<div id="div"></div>

Browser other questions tagged

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