Ember.js Router: How to animate state transitions
Asked Answered
I

6

25

Has somebody found a good way to animate state transitions?

The router immediately removes the view from the DOM. The problem with that is that I can't defer that until the end of the animation. Note: I'm using v1.0.0-pre.4.

Incurvate answered 25/1, 2013 at 12:29 Comment(2)
Have you considered adding the transition classes to your view through Ember.View#willDestroyElement?Wormy
fwiw, my answer below about ember liquid fire is considered the best practice today for this type of situation :)Janicejanicki
F
10

Billy's Billing just released an Ember module that supports animated transitions.

Floeter answered 9/4, 2013 at 23:1 Comment(1)
I am just starting with ember. The linked page says: "Things to be aware of: [...] Animations are not executed when transitioning to the same route with a different model. This is due to the way Ember reuses the same DOM element, and will likely not be fixed until animation support lands in Ember core in 1.1." So my question - is this answer up to date? What is the best option with emper 2.10 to animate routes?Muskogean
W
7

I'll expand on Lesyk's answer. If you need to apply it to multiple views in a DRY way, you can create a customization class like this:

App.CrossfadeView = {
  didInsertElement: function(){
    //called on creation
    this.$().hide().fadeIn(400);
  },
  willDestroyElement: function(){
    //called on destruction
    this.$().slideDown(250);
  }
};

And then in your code you apply it on your various view classes. As Ember depends on jQuery you can use pretty much any jQuery animation.

App.IndexView = Ember.View.extend(App.CrossfadeView);
App.PostView = Ember.View.extend(App.CrossfadeView);
Wail answered 25/1, 2013 at 12:29 Comment(4)
The end of the first code snippet is wrong, brackets don't match up :) Maybe you could edit that.Nakashima
The willDestroyElement animation doesn't work for me (1.0-rc4). It seems that the view is already gone before the animation renders. Do you have a working example?Nakashima
Here is an (unfinished) example using that. The animation works tho: jsbin.com/imahog/21/edit Do note that I'm using rc6 tho, and you were right abut the brackets (fixed it above).Wail
Thanks. fadeIn works indeed, but the slideDown in willDestroyElement is not visible, at least for me.Nakashima
J
7

I know this is pretty old, but the best solution for this context-specific animation today is probably ember liquid fire.

It allows you to do things like this in a transition file:

export default function(){
  this.transition(
    this.fromRoute('people.index'),
    this.toRoute('people.detail'),
    this.use('toLeft'),
    this.reverse('toRight')
  );
};
Janicejanicki answered 10/3, 2015 at 20:42 Comment(0)
J
6

Ran into this same requirement on my app. Tried Ember Animated Outlet, but didn't give the granularity I needed (element specific animations).

The solution that worked for me was as follows --

Change linkTo to be an action

{{#linkTo "todos"}}<button>Todos</button>{{/linkTo}}

Becomes...

<a href="#/todos" {{action "goToTodos"}}><button>Todos</button></a>

Create Method for goToTodos in current controller

App.IndexController = Ember.Controller.extend({
    goToTodos: function(){

        // Get Current 'this' (for lack of a better solution, as it's late)
            var holdThis = this;

        // Do Element Specific Animation Here
            $('#something').hide(500, function(){

                // Transition to New Template
                    holdThis.transitionToRoute('todos');

            });

    }
});

Finally -- To animate in elements on the Todos Template, use didInsertElement on the view

App.TodosView = Ember.View.extend({
    didInsertElement: function(){

        // Hide Everything
            this.$().hide();

        // Do Element Specific Animations Here
            $('#something_else').fadeIn(500);

    }
});

So far, this is the most elegant solution I've found for element specific animations on transition. If there is anything better, would love to hear!

Jacobsohn answered 10/7, 2013 at 7:32 Comment(1)
You're not talking about state transitions if you're animating individual elements. ember-animated-OUTLET is for outlets, which is purportedly different than the OP's use case. Furthermore, actions break the URL support of the app :-(Reversible
B
4

I've found another drop-in solution that implements animations in Views: ember-animate

Example:

App.ExampleView = Ember.View.extend({

    willAnimateIn : function () {
        this.$().css("opacity", 0);
    },

    animateIn : function (done) {
        this.$().fadeTo(500, 1, done);
    },

    animateOut : function (done) {
        this.$().fadeTo(500, 0, done);
    }
}

Demo: author's personal website

Bolling answered 6/2, 2014 at 9:35 Comment(0)
R
1
App.SomeView = Ember.View.extend({
  didInsertElement: function(){
   //called on creation
   this.$().hide().fadeIn(400);
  },
  willDestroyElement: function(){
   //called on destruction
   this.$().slideDown(250)
  }
});
Rafaellle answered 25/1, 2013 at 17:42 Comment(1)
I do know those hooks, however none of those helps me get the job done. The problem is that didInsertElement and willDestroyElement are specific to that very view. To make a transition smooth, I'd need to know whether the other view, the one that the router is transitioning to, is ready, then do the animation/transition and then detroy the previous view. So in other words I'm looking for a more async-behaviour.Incurvate

© 2022 - 2024 — McMap. All rights reserved.