Closed wesleycho closed 8 years ago
animateCss actually already has a timeout that should end the animation after (I think) duration * 1.5. That the end listener isn't executed seems like a bug, though. Or maybe that's because animateCss should be used mainly in the context of js animations, not as a replacement for general animations.
I think this is the problem: https://github.com/angular/angular.js/issues/12691 $animateCss wasn't designed as an all out replacement for $animate. Hmm ... Why did bootstrap-ui change to using animateCss?
I thought $animateCss was recommended for when the transitions were purely from CSS classes? Was I mistaken there?
I've no problem changing it to $animate here if that's what does the trick.
I took a look at changing it to $animate, I am seeing this same problem still - I believe the $animate.on('addClass', ...)
listener is not getting called on completion of the custom JS animation here. Is that a possibility?
Ok, that's weird. I have a look tomorrow
We are seeing this same issue. It appears to be related to AnimationRunner._tick switching to timeouts when in a background tab.
It is completely non-deterministic, but when it occurs you won't see another update until the app switches back to using $$raf to schedule updates.
I am running into an issue with angular 1.5.0 and 1.4.9 where animations are delayed when switching to a different tab and then coming back. It's as if the digest cycle doesn't take place for a few seconds after switching back to the tab. I tried reverting 9a60408c804a62a9517857bdb9a42182ab6769e3 locally and the problem was fixed. As @jgrund mentioned above, when the problem occurs, the update doesn't take place until the $$raf update takes place.
So we actually switched from using $$rAF when the page is hidden to $timeout because most browsers don't flush requestAnimationFrame when the page is hidden. A simple demo obviously helps with fixing this.
So the problem is that we don't notify progress when the animation is skipped. (it is skipped because the document is hidden). "Skipping" means that no animation is performed - classes and styles etc. are applied as you would expect. Progress events are for listeners registered with $animate.on(event, element, callbackFn)
, where event is for example 'addClass' or ' enter'
So we have a few scenarios for which we need to define the behavior:
What happens to an animation that is started while the document is hidden? (e.g the case of the slideshow, when a transition is started while the document is hidden)
I think option 1 is what makes most sense. Option 2 would actually be very diffcult to implement. Fwiw, I think the behavior before the timeout tick "fix" was that of option 2. The animation listeners would only be resolved when the document became visible again.
Since there are more conditions under which an animation is skipped, I have to check in which cases it makes sense to fire the animation callbacks, and in which it doesn't. My hunch is that you will want the listeners almost always to fire, even if no actual animation is performed.
Should animation progress listeners be fired when ngAnimate is not included?
At the moment, we don't notify progress without ngAnimate at all, even though the docs suggest we do. If this worked, then 3rd party module developers wouldn't have to have two paths for animations enabled / not enabled. We also execute the then
and done
functions of the runner without ngAnimate. I think we changed this pretty recently, so I assume the intention is to actually fire all listeners always.
Should animateCss notify progress listeners if used programmatically? Atm, animateCss doesn't notify progress at all at the moment if it is used programmatically. It does notify when it is used by the general animation service ($animate) and when it is used inside javascript animations (which are also called from $animate).
@matsko I would like your opinion on this
Just FYI we were also able to reproduce this when not loading the ngAnimate module.
@jgrund Do you mean the $animate.on() listeners are not fired when ngAnimate is not included and the document is hidden? At the moment, they never fire without ngAnimate. This is one of the points I raised in https://github.com/angular/angular.js/issues/14120#issuecomment-188755085
@Narretz I mean, whenever the runner switches to timeouts in a background tab, the state of our app does not update upon refocusing. This occurs whether ngAnimate has been loaded or not.
@jgrund Can you please provide a demo of that problem? Because I cannot reproduce it in this app with ngAnimate removed: http://plnkr.co/edit/pGRtrLoA7NOWfeOAQYnW?p=preview
Note: for support questions, please use one of these channels: https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#question. This repository's issues are reserved for feature requests and bug reports.
Bug
In certain situations, when the user switches to a different tab, the
transitionend
event is not fired - this is a documented browser defect with Firefox here, and seems to be reproducible in Chrome at the least.Not minimal unfortunately, but here is an example from UI Bootstrap. Source code for component can be found here - in particular, the culprit is that this listener never fires due to this browser defect, which causes the callback to never execute.
The
transitionend
event fires and the slides continue rotating since the$currentTransition
internal state is reset.My proposal is to have ngAnimate use the computed style information to manually fire the
transitionend
event if it is never fired to cause the listeners to be resolved - a timeout for the transition time period + 1 ms would be satisfactory to me, which would prevent library maintainers to have to do an extragetComputedStyle
call & an extra calculation of the transition time length. This is a hack, but this is the least onerous solution IMO.Angular 1.4+ when using $animateCss instead of $animate. This affects at the least Chrome & Firefox across all OSs at the least.