In my Meteor app I have some plex page animations that require a few seconds to plete (instructive animations take priority over page transition speed).
There's an out state and an in state in the animation. For simplicity's sake, let's say I need to fade out one page, and then fade in the next, but that I want those fades to take multiple seconds. To do this I use Meteor's Iron Router to call some animation functions that manipulate the CSS.
lib/router.js
animateContentOut = function(pause) {
return $('#content').removeClass("animated fadeIn");
}
Router.onAfterAction(animateContentOut);
animateContentIn = function() {
return $('#content').addClass("animated fadeIn");
}
Router.onAfterAction(animateContentIn);
This is based on a great tip from Manuel Schoebel and the fadeIn works. However, my fade animation takes several seconds. So the user only sees the first few miliseconds of the fadeOut animation because it starts and then the router quickly navigates away to the new route before the animation pletes.
So my question, is: how can I tell the router to wait for the animation to plete or for a setTimeout on an action in the onAfterAction call? Is there a better hook to use when animating the process of leaving a page?
In my Meteor app I have some plex page animations that require a few seconds to plete (instructive animations take priority over page transition speed).
There's an out state and an in state in the animation. For simplicity's sake, let's say I need to fade out one page, and then fade in the next, but that I want those fades to take multiple seconds. To do this I use Meteor's Iron Router to call some animation functions that manipulate the CSS.
lib/router.js
animateContentOut = function(pause) {
return $('#content').removeClass("animated fadeIn");
}
Router.onAfterAction(animateContentOut);
animateContentIn = function() {
return $('#content').addClass("animated fadeIn");
}
Router.onAfterAction(animateContentIn);
This is based on a great tip from Manuel Schoebel and the fadeIn works. However, my fade animation takes several seconds. So the user only sees the first few miliseconds of the fadeOut animation because it starts and then the router quickly navigates away to the new route before the animation pletes.
So my question, is: how can I tell the router to wait for the animation to plete or for a setTimeout on an action in the onAfterAction call? Is there a better hook to use when animating the process of leaving a page?
Share Improve this question asked Jul 23, 2014 at 15:57 bryan kennedybryan kennedy 7,2196 gold badges45 silver badges65 bronze badges 2- You may want to see github./tmeasday/iron-transitioner and its current branches in github./percolatestudio/iron-transitioner. – Andrew Mao Commented Jul 24, 2014 at 16:14
- I dug into the different branches on the transitioner, but I couldn't figure out how to make it work with my view/template structure. It seemed like I couldn't do transitions between different views. But, I might not have looked close enough. – bryan kennedy Commented Jul 24, 2014 at 19:40
2 Answers
Reset to default 6It depends what's generating the change of page. If it's a link/button/generic event, then rather than using an anchor href, you could just register an event like below, and store the route you want to move to (like "/home") in the data-route
attribute of the anchor tag:
Template.links.events({
'click a': function(event) {
var _currentTarget = event.currentTarget;
$('#content').removeClass('animated fadeIn').on('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd', function() {
Router.current().redirect(_currentTarget.attributes['data-route'].value);
});
}
});
That should begin the fade out, and actually wait for it to end before changing the route. A few caveats:
- It won't do anything for you if the user manually changes the url, and you'll have to add it to every piece of logic that changes page - to avoid either of these problems you'll probably have to pick apart the iron-router code and find a way to hook into page changes, which I'm not in a position to do at present!
- I haven't tested cross-browser, but it works fine in Chrome.
- In my experience you need to be careful with the
currentTarget
property of an event in Meteor - I don't think it will always give you what you expect, but this is something I need to take up separately.
I have run into same question, when trying to bine Meteor with Framework7. Here is solution that absolutely works for me:
Meteor.startup(function () {
var _animationEnd = 'oanimationend animationend webkitAnimationEnd otransitionend oTransitionEnd msTransitionEnd mozAnimationEnd MSAnimationEnd',
_enterAnimation = 'fadeIn animated',
_leaveAnimation = 'fadeOut animated',
_animate = function ($el, anim, next) {
return $el.addClass(anim)
.on(_animationEnd, function () {
$(this).removeClass(anim);
next && next();
});
};
Router.onAfterAction(function () {
_animate($(".view-main"), _enterAnimation);
});
$(document.body).click(function (event) {
var $t = $(event.target).parents().andSelf().filter("[href]:last"), url;
if ($t.size() && (url = $t.attr('href'))) {
var currentRoute = Router.current();
_animate($(".view-main"), _leaveAnimation, function () {
currentRoute.redirect(url);
});
event.preventDefault(), event.stopPropagation();
}
});
});
Comments and pros vs. solution provided by richsilv:
- It works for all templates you ever use, since it's using body events
- It works with any element, even a.href's, since preventing click event from default and further propagation
- It is more patible with other browsers, since more "animationend/transitionend/etc" events listed