簡體   English   中英

Angular 2 - 如何在指令上設置動畫?

[英]Angular 2 - How to set animations on a Directive?

我有一個Directive我可以放在元素上,檢查相關元素的當前滾動位置。

看起來像這樣:

@Directive({
    selector: '[my-scroll-animation]'
})

每當位置滿足某個閾值時,我希望元素使用動畫出現在屏幕上。 我知道對於一個Component我可以附加一個animations屬性以及host屬性中的一些設置來激活動畫。

我想要這樣的東西:

import { myScrollAnimation } from './animations';

@Directive({
    selector: '[my-scroll-animation]'
    animations: [myScrollAnimation] // <- not possible?
})

我怎樣才能在指令中實現這一點?

使用:Angular 4.0.0-rc.4

Angular 4.2 帶來了很多動畫改進。 其中之一是 AnimationBuilder,它允許程序化的動畫構建。

您只需要在指令中注入 AnimationBuilder,就可以將任何 AnimationMetadata 轉換為工作動畫。

@Directive({
  selector: '[zetFadeInOut]',
})
export class FadeInOutDirective {
  player: AnimationPlayer;

  @Input()
  set show(show: boolean) {
    if (this.player) {
      this.player.destroy();
    }

    const metadata = show ? this.fadeIn() : this.fadeOut();

    const factory = this.builder.build(metadata);
    const player = factory.create(this.el.nativeElement);

    player.play();
  }

  constructor(private builder: AnimationBuilder, private el: ElementRef) {}

  private fadeIn(): AnimationMetadata[] {
    return [
      style({ opacity: 0 }),
      animate('400ms ease-in', style({ opacity: 1 })),
    ];
  }

  private fadeOut(): AnimationMetadata[] {
    return [
      style({ opacity: '*' }),
      animate('400ms ease-in', style({ opacity: 0 })),
    ];
  }
}

我有點用一種變通方法的基礎上這一響應benshabatnoam的回答中提到的問題。

指令實際上只是沒有模板的組件。 您可以通過使用屬性選擇器(例如: [selector] )並制作模板: <ng-content></ng-content>來創建一個與指令相同的組件。

因此,您可以創建一個“foux-directive”組件,如下所示:

@Component({
    selector: '[fadeInAnimation]',
    animations: [
        trigger('fadeIn', [
             transition(':enter', [
                 style({opacity:'0'}),
                 animate(200, style({opacity:'1'}))
             ])
        ])
    ], 
    template: `<ng-content></ng-content>`,
})
export class FadeInDirective {
    @HostBinding('@fadeIn') trigger = '';
}

並像使用任何指令一樣使用它:

<div fadeInAnimation> something I want to animate </div>

正如我在您問題的評論部分中提到的。

您可以在父組件中進行動畫配置。 然后該指令在滿足閾值時在其主機上添加一個類。

在您的指令中,您可以有以下內容:

@Input() classThatTriggersAnimation = "do-animation";
@HostBinding('[@nameOfAnimation]') animationTrigger = ""; 

// when logic is true
this.animationTrigger = this.classThatTriggersAnimation;

這是 Angular 的 git 存儲庫中的一個懸而未決的問題(截至今天 - 28/08/17)。 請對此問題進行投票,以便向開發人員施加壓力以加快發布速度。

開始了。 適合小動畫。

我直接使用AnimationPlayer + AnimationBuilder => 不需要人為地前后切換狀態來觸發動畫。 受此片段的啟發並進一步簡化。

import { Directive, Input, HostListener } from '@angular/core';
import { ElementRef } from '@angular/core';
import {
    AnimationPlayer,
    AnimationBuilder
} from '@angular/animations';

@Directive({
    selector: '[clickAnimation]',
})
export class ClickAnimationDirective {
    private player: AnimationPlayer;

    @Input() clickAnimation: any;

    @HostListener('click', ['$event'])
    onClick() {
        // sanitize just in case
        if (this.player) { this.player.destroy(); }

        const factory = this.builder.build(this.clickAnimation);
        const player = factory.create(this.el.nativeElement);

        // ensure back-to-original
        player.onDone(() => { player.reset(); });
        player.play();
    }

    constructor(private builder: AnimationBuilder, private el: ElementRef) { }
}

在您的模板中:

<app-button
    [clickAnimation]="trafficLight"
    ...

在您的組件類中:

public trafficLight: AnimationMetadata[] = [
    style({ borderColor: 'red' }),
    animate('400ms ease-in', style({ borderColor: 'yellow' })),
    animate('400ms ease-in', style({ borderColor: 'cyan' })),
    //alternative way to ensure back to original
    // animate('400ms ease-in', style({ borderColor: '*' })), 
];

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM