简体   繁体   English

Aurelia.js:当绑定值更改时,如何为元素设置动画?

[英]Aurelia.js: How do I animate an element when bound value changes?

I am using Aurelia.js for my UI. 我正在使用Aurelia.js作为我的UI。 Let's say I have the following view markup: 假设我有以下视图标记:

<tr repeat.for="item in items">
    <td>${item.name}</td>
    <td>${item.value}</td>
</tr>

Which is bound to a model "items". 哪个是模型“项目”。 When one of the values in the model changes, I want to animate the cell where the changed value is displayed. 当模型中的某个值发生更改时,我想为显示更改值的单元格设置动画。 How can I accomplish this? 我怎么能做到这一点?

This can be done with Aurelia custom attributes feature. 这可以使用Aurelia 自定义属性功能完成。

Create a new javascript file to describe the attribute (I called the attribute "animateonchange"): 创建一个新的javascript文件来描述属性(我称之为属性“animateonchange”):

import {inject, customAttribute} from 'aurelia-framework';
import {CssAnimator} from 'aurelia-animator-css';

@customAttribute('animateonchange')
@inject(Element, CssAnimator)
export class AnimateOnChangeCustomAttribute {
    constructor(element, animator) {
        this.element = element;
        this.animator = animator;
        this.initialValueSet = false;
    }

    valueChanged(newValue){
        if (this.initialValueSet) {
            this.animator.addClass(this.element, 'background-animation').then(() => {
                this.animator.removeClass(this.element, 'background-animation');
            });
        }
        this.initialValueSet = true;
    }
}

It receives the element and CSS animator in constructor. 它在构造函数中接收元素和CSS动画。 When the value changes, it animates the element with a predefined CSS class name. 当值更改时,它会使用预定义的CSS类名称为元素设置动画。 The first change is ignored (no need to animate on initial load). 忽略第一个更改(无需在初始加载时设置动画)。 Here is how to use this custom element: 以下是如何使用此自定义元素:

<template>
    <require from="./animateonchange"></require>
    <div animateonchange.bind="someProperty">${someProperty}</div>
</template>

See the complete example in my blog or on plunkr 请参阅我的博客plunkr中的完整示例

The creator of the crazy Aurelia-CSS-Animator over here :) 疯狂的Aurelia-CSS-Animator的创造者在这里:)

In order to do what you want you simply need to get hold of the DOM-Element and then use Aurelia's animate method. 为了做你想做的事,你只需要掌握DOM-Element,然后使用Aurelia的animate方法。 Since I don't know how you're going to edit an item, I've just used a timeout inside the VM to simulate it. 由于我不知道你将如何编辑项目,我只是在VM内部使用了一个超时来模拟它。

attached() {
  // demo the item change
  setTimeout( () => {
    let editedItemIdx = 1;

    this.items[editedItemIdx].value = 'Value UPDATED';
    console.log(this.element);
    var elem = this.element.querySelectorAll('tbody tr')[editedItemIdx];

    this.animator.addClass(elem, 'background-animation').then(() => {
      this.animator.removeClass(elem, 'background-animation')
    });
  }, 3000);
}

I've created a small plunkr to demonstrate how that might work. 我已经创建了一个小型的plunkr来演示它是如何工作的。 Note this is an old version, not containing the latest animator instance, so instead of animate I'm using addClass/removeClass together. 请注意,这是一个旧版本,不包含最新的animator实例,因此我将使用addClass / removeClass而不是动画。

http://plnkr.co/edit/7pI50hb3cegQJTXp2r4m http://plnkr.co/edit/7pI50hb3cegQJTXp2r4m

Also take a look at the official blog post, with more hints http://blog.durandal.io/2015/07/17/animating-apps-with-aurelia-part-1/ 另请查看官方博客文章,更多提示http://blog.durandal.io/2015/07/17/animating-apps-with-aurelia-part-1/

Hope this helps 希望这可以帮助

Unfortunately the accepted answer didnt work for me, the value in display changes before any animation is done, it looks bad. 不幸的是,接受的答案对我没有用,显示的值在任何动画完成之前发生变化,看起来很糟糕。

I solved it by using a binding behavior, the binding update is intercepted and an animation is applied before, then the value is updated and finally another animation is done. 我通过使用绑定行为来解决它,拦截绑定更新并在之前应用动画,然后更新值,最后完成另一个动画。 Everything looks smooth now. 一切看起来都很顺利。

    import {inject} from 'aurelia-dependency-injection';  
import {CssAnimator} from 'aurelia-animator-css';



@inject(CssAnimator)
export class AnimateBindingBehavior {

  constructor(_animator){
    this.animator = _animator;
  }

  bind(binding, scope, interceptor) {

    let self = this;

    let originalUpdateTarget =  binding.updateTarget;

    binding.updateTarget = (val) => {
      self.animator.addClass(binding.target, 'binding-animation').then(() => {
        originalUpdateTarget.call(binding, val);
        self.animator.removeClass(binding.target, 'binding-animation')
      });
    }
  }

  unbind(binding, scope) {
    binding.updateTarget = binding.originalUpdateTarget;
    binding.originalUpdateTarget = null;
  }
}

Declare your animations in your stylesheet: 在样式表中声明您的动画:

@keyframes fadeInRight {
  0% {
    opacity: 0;
    transform: translate3d(100%, 0, 0);
  }
  100% {
    opacity: 1;
    transform: none
  }
}


@keyframes fadeOutRight {
  0% {
    opacity: 1;
    transform: none;
  }
  100% {
    opacity: 0;
    transform: translate3d(-100%, 0, 0)
  }
}


    .binding-animation-add{
      animation: fadeOutRight 0.6s;
    }

    .binding-animation-remove{
      animation: fadeInRight 0.6s;
    }

You use it in your view like 你可以在你的视图中使用它

<img src.bind="picture & animate">

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM