Ember.js 路由器:如何动画状态转换

Posted

技术标签:

【中文标题】Ember.js 路由器:如何动画状态转换【英文标题】:Ember.js Router: How to animate state transitions 【发布时间】:2013-01-09 10:03:48 【问题描述】:

有人找到了一种动画状态转换的好方法吗?

路由器立即从 DOM 中删除视图。问题是我不能推迟到动画结束。注意:我使用的是 v1.0.0-pre.4

【问题讨论】:

您是否考虑过通过Ember.View#willDestroyElement将过渡类添加到您的视图中? fwiw,我在下面关于ember liquid fire 的回答被认为是当今这种情况的最佳实践:) 【参考方案1】:
App.SomeView = Ember.View.extend(
  didInsertElement: function()
   //called on creation
   this.$().hide().fadeIn(400);
  ,
  willDestroyElement: function()
   //called on destruction
   this.$().slideDown(250)
  
);

【讨论】:

我确实知道那些钩子,但是这些都不能帮助我完成工作。问题是 didInsertElementwillDestroyElement 是特定于该视图的。为了使过渡平滑,我需要知道路由器正在过渡到的另一个视图是否已准备好,然后进行动画/过渡,然后销毁前一个视图。所以换句话说,我正在寻找一种更 async-behaviour.【参考方案2】:

Billy's Billing 刚刚发布了一个支持动画过渡的 Ember module。

【讨论】:

我只是从 ember 开始。链接页面说:“需要注意的事情:[...] 使用不同模型转换到相同路线时不会执行动画。这是由于 Ember 重用相同 DOM 元素的方式,并且可能不会修复直到动画支持在 1.1 的 Ember 核心中落地。”所以我的问题 - 这个答案是最新的吗?使用 emper 2.10 动画路线的最佳选择是什么?【参考方案3】:

我将扩展 Lesyk 的答案。如果您需要以 DRY 方式将其应用于多个视图,您可以创建一个自定义类,如下所示:

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

然后在您的代码中将其应用于各种视图类。由于 Ember 依赖于 jQuery,因此您几乎可以使用任何 jQuery 动画。

App.IndexView = Ember.View.extend(App.CrossfadeView);
App.PostView = Ember.View.extend(App.CrossfadeView);

【讨论】:

第一个代码 sn-p 的结尾是错误的,括号不匹配:) 也许你可以编辑它。 willDestroyElement 动画对我不起作用(1.0-rc4)。似乎在动画渲染之前视图已经消失了。你有一个可行的例子吗? 这是一个使用它的(未完成的)示例。动画有效:jsbin.com/imahog/21/edit 请注意,我使用的是 rc6,而您正好紧靠括号(在上面固定)。 谢谢。 fadeIn 确实有效,但 willDestroyElement 中的 slideDown 不可见,至少对我来说是这样。【参考方案4】:

在我的应用程序中遇到了同样的要求。试过Ember Animated Outlet,但没有给出我需要的粒度(特定于元素的动画)。

对我有用的解决方案如下--

linkTo 更改为 action

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

变成……

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

在当前控制器中为 goToTodos 创建方法

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');

            );

    
);

最后 -- 要在 Todos 模板上的元素中设置动画,请在视图上使用 didInsertElement

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

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

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

    
);

到目前为止,这是我为元素特定的过渡动画找到的最优雅的解决方案。如果有更好的,很想听听!

【讨论】:

如果您正在为单个元素设置动画,那么您不是在谈论状态转换。 ember-animated-OUTLET 用于插座,据称与 OP 的用例不同。此外,操作会破坏应用程序的 URL 支持 :-(【参考方案5】:

我发现了另一个在视图中实现动画的插入式解决方案:ember-animate

例子:

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);
    

演示:author's personal website

【讨论】:

【参考方案6】:

我知道这已经很老了,但今天这个特定于上下文的动画的最佳解决方案可能是ember liquid fire。

它允许你在转换文件中做这样的事情:

export default function()
  this.transition(
    this.fromRoute('people.index'),
    this.toRoute('people.detail'),
    this.use('toLeft'),
    this.reverse('toRight')
  );
;

【讨论】:

考虑到 EmberJS 在升级过程中确实像疯了一样波动,旧帖子上的任何新信息都应该受到欢迎。所以谢谢你!

以上是关于Ember.js 路由器:如何动画状态转换的主要内容,如果未能解决你的问题,请参考以下文章

在页面转换完成时暂停 Meteor 的 Iron Router 中的路由

如何使用错误子状态在Ember.js中显示整页错误?

布局中的 Qt 状态机转换

角度动画性能状态/转换与查询

UIButton 的正常状态和突出显示状态之间的动画转换

动画选择器/状态转换