In my Meteor app I have some complex page animations that require a few seconds to complete (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 completes.
So my question, is: how can I tell the router to wait for the animation to complete 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?
It 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 combine 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 compatible with other browsers, since more "animationend/transitionend/etc" events listed
来源:https://stackoverflow.com/questions/24915357/pause-routing-in-meteors-iron-router-while-a-page-transition-completes