在Emberjs破坏之前制作动画

时间:2013-02-26 15:14:43

标签: ember.js

目前无法延迟Ember中的视野破坏。 如果要在销毁视图之前为其设置动画,则会出现此问题。

所以,我目前有这个非常丑陋的解决方法:

willDestroyElement: ->
  $clone = @$().clone().addClass "animate-destruction"
  @$().parents(':first').prepend $clone
  setTimeout ->
    $clone.off().remove()
  , 350

注意:动画是在css。{/ p>中的.animate-destruction类中完成的

我知道我的方法很糟糕,所以我想知道是否有人提出了更好的方法。

3 个答案:

答案 0 :(得分:1)

这只是我身边的一个自发想法:

这是Ember.View(Link to Source)中的destroyElement的实现:

 destroyElement: function() {
    return this.currentState.destroyElement(this);
  },

您可以尝试覆盖此方法来制作动画:

destroyElement: function() {
    var completeCallback = function(){
        return this.currentState.destroyElement(this);
    }
    this.$().fadeOut(completeCallback); //or whatever animation
},

答案 1 :(得分:1)

试试这个

Ember.Route.extend({
actions: {
willTransition: function(transition) {
        $.each(Ember.View.views, function(index, value) {
            var popUpView = value.get('classNames').find(function(item) {
                return item == '[nameofyourclass]';
            });
            if(!Em.isEmpty(popUpView) && value.get('visible')) {
                value.set('visible', false);
                value.get('controller').set('previousTransition', transition);
                transition.abort();
            }
        });
        return true;
},
 }
    });

Ember.View.extend({
classNames: ['nameofyourclass'],
classNameBindings: ['visible:element-visible'],

visible: false,

didInsertElement: function() {
    var t = this,
            controller = this.get('controller');
    this.$()
    .on('transitionend webkitTransitionEnd oTransitionEnd MSTransitionEnd', function() {
        if(!t.get('visible')) {
            var previousTransition = controller.get('previousTransition');
            if(!Em.isEmpty(previousTransition)) {
                controller.set('previousTransition', null);
                previousTransition.retry();
            } else { // fallback
                controller.transitionToRoute('index');
            }
        }
    });
    Em.run.next(this, function() {
        this.set('visible', true);
    });
},
});

答案 2 :(得分:0)

我处理pre-destroy动画的首选方法是使用Em.Evented。让视图侦听在方法或操作中调用的事件,该事件将开始销毁视图并延迟销毁,直到事件触发的方法完成(使用运行循环)。例如:

SomeView = Em.View.extend({

  _listen: function() {
    this.get('controller').on('closeChildView', this, this.hide);
  }.on('willInsertElement'),

  hide: function() {
    this.$().fadeOut(this.get('controller.duration'));
  }

});

然后在控制器中:

Em.ObjectController.extend(
  Em.Evented, { // Important mixin!

  duration: 500,

  actions: {
    removeSomeChildView: function() {
      this.trigger('closeChildView');

      Em.run.later(this, function() {
        // Then do the stuff to destroy the view here.
      }, this.get('duration'));
    }
  }

});

或者,您可以在视图中使用this.removeFromParent()方法来合并隐藏和删除视图。

如果破坏实际上是在视图中启动的,那么在调用destroy方法之前可以使用这些相同的原则,如果在视图后需要回调,请使用.on('willDestroyElement')向控制器或路由发送操作已被删除。

通过在this.$().hide上运行didInsertElement,然后使用show()方法转换视图元素,可以以相同的方式完成预破坏动画。

调整JS和CSS转换时间

如果你在CSS中进行所有转换,你需要确保CSS和JS之间的转换时间是一致的。这很简单。在您的视图中,确保CSS转换发生在视图的元素上,然后:

SomeView = Em.View.extend({
  transitionDuration: Em.computed.alias('controller.transitionDuration'),

  setTransitionDuration: function() {
    var ms = parseFloat(this.$().css('transition-duration')) * 1000; // In milliseconds

    if (ms) {
      this.set('transitionTime', ms);
    }
  }.on('didInsertElement'),
});

这将更新视图和控制器上的转换持续时间,以匹配您在CSS中编写的任何内容。您在控制器上为transitionDuration指定的值是transitionDuration的后备值,如果您想在覆盖默认JS {{}}之前进行一些验证,则可以在上述方法中添加if () {1}}。