angularjs - Google I/O 2015 page like transition animations -
recently google i/o 2015 event page, transition animations between different states. know used polymer that, i'm trying recreate such delayed animations in angular (1.4.1) , angular-material , ui-router.
basically want achieve workflow:
- before state change, animate leaving components of app
- leave basic structure of app (some basic holder containers)
- make state change - resolve resources (rest api call)
- transition new state, basic app structure (holders)
- animate entering elements (with different delays)
this not trivial task, , ng-animate not helpful, want use as possible. 1 drawback is, leaving css classes not added, before promises resolved, other it, @ 1 moment, both - old , new state view present on page.
i tried create directive:
(function() { 'use strict'; angular .module('climbguide') .directive('cganimateelement', cganimateelement); /* @nginject */ function cganimateelement($animate, $rootscope, $state) { return { restrict: 'a', link: linkfunc }; function linkfunc(scope, el) { $animate.enter(el, el.parent()); var cleanup = $rootscope.$on('$statechangestart', function(event, tostate, toparams) { if ($rootscope.statechangebypass) { $rootscope.statechangebypass = false; return; } event.preventdefault(); var promise = $animate.leave(el); promise.then(function() { $rootscope.statechangebypass = true; $state.go(tostate.name, toparams); }); }); scope.$on('$destroy', function() { cleanup(); }); } } })();
it want, reason possible use 1 element - assume because of $rootscope.$on('$statechangestart') , later use of $state.go(tostate.name, toparams);.
i found 2 other solutions,
angular-ui-router-in-out, uses css, there waiting promises resolved before animation happens (the loader animation necessary)
angular-gsapify-router, uses javascript animations, , has same problem above one.
i'm still learning angular, don't know how in right way. have ideas? lot.
p.s.: sorry missing links libraries, first post so, can post 2 links :)
maybe somebody, got work dirty hack, anyway does, described in original post.
i changed directive can re-used more times:
(function() { 'use strict'; angular .module('climbguide') .directive('cganimateelement', cganimateelement); /* @nginject */ function cganimateelement($animate, delayedrouterservice) { return { restrict: 'a', link: linkfunc }; function linkfunc(scope, el) { var statechangebypass = false; $animate.enter(el, el.parent()); // use scope instead of $rootscope, there no need de-register listener scope.$on('$statechangestart', function(event, tostate, toparams) { if (statechangebypass) { // resuming transition next state broadcasts new $statechangestart // event, necessary bypass statechangebypass = false; return; } delayedrouterservice.holdstatechange(event); var promise = $animate.leave(el); promise.then(function() { statechangebypass = true; delayedrouterservice.releasestatechange(tostate, toparams); }); }); } } })();
i created service handling state changes - preventing , resuming state changes in ui-router:
(function() { 'use strict'; angular .module('climbguide') .factory('delayedrouterservice', delayedrouterservice); /* @nginject */ function delayedrouterservice($state) { var _runninganimations = 0; /** * public methods * */ var service = { holdstatechange: holdstatechange, releasestatechange: releasestatechange }; return service; ////////////// /** * prevent state change first animation * store number of running animations * * @param event */ function holdstatechange(event) { if (_runninganimations === 0) { event.preventdefault(); } _runninganimations++; } /** * remove animation stack after finished * resume state transition after last animation finished * * @param tostate * @param toparams */ function releasestatechange(tostate, toparams) { _runninganimations--; if (_runninganimations === 0) { $state.go(tostate.name, toparams); } } } })();
so it's possible use in html element want animate
<div class="main" cg-animate-element> ... </div>
and final css:
.main { &.ng-animate { transition: opacity, transform; transition-duration: 0.4s; transition-timing-function: cubic-bezier(0.42, 0, 0.58, 1); } &.ng-enter { opacity: 0; transform: translate3d(0, 100px, 0); } &.ng-enter-active { opacity: 1; transform: translate3d(0, 0, 0); } &.ng-leave { opacity: 1; transform: translate3d(0, 0, 0); } &.ng-leave-active { opacity: 0; transform: translate3d(0, 100px, 0); } }
Comments
Post a Comment