Angular 动画 - 动态和响应式翻译

Angular Animations - Dynamic and Responsive translations

我有一个通常处于休眠状态的组件(我只是说它对用户没什么兴趣),但在某种状态下这个组件变成 'activated' 我想把它放在屏幕的确切中心并将其放大以吸引用户的注意力。

这些组件中有多个处于休眠状态,但只有 1 个处于激活状态。休眠组件可以在屏幕上的任何位置,所以我想要一个解决方案,可以在激活时将组件从它最初所在的位置转换到屏幕中间,然后 return 完成后它回到原来的休眠位置.

正在尝试这样做:

模板:

<div #myElement [@isActivated]="activated">
    Hello Stack Overflow
    <button (click)="activated = activated === 'activated' ? 'dormant' : 'activated">
        Toggle
    </button>
</div>

打字稿:

@Component({
  // ...
  animations: [
    trigger('isActivated', [
      state('dormant', style($transitionToActivated)),
      state('activated', style({
        transform: 'translateX(0%) translateY(0%) scale(1)'
      })),
      transition('dormant => activated', animate('1000ms ease')),
      transition('activated => dormant', animate('1000ms ease'))
    ])
  ]
})
export class MyComponent implements OnInit {
    @ViewChild('myElement') myElement: ElementRef;
    activated = 'dormant';
    transitionToActivated: any;

    ngOnInit() {
        let rect = this.myElement.nativeElement.getBoundingClinetRect();
        this.transitionToActivated = {
            transform: ''translateX(' + ((window.screen.width / 2) - (rect.right + rect.left) / 2) + ') translateY(' +
                ((window.screen.height / 2) - (rect.top + rect.bottom) / 2) + ') scale(1.5)'
        }
    }
}

我这里的语法是错误的:Component 装饰器中的 $transitionToActivated 无效。 Angular 动画可以实现这种响应式动画吗?或者我需要研究一个纯粹的 CSS 解决方案吗?

[这是我正在尝试的 plunker...目前我试图将它放在确切中心的尝试已被注释掉,只有一些静态动画说明]

我想通了一些事情。

首先,上面我使用 window.screen 作为 'screen.' 的宽度和高度这实际上是给我显示器的分辨率(调整 window 的大小不影响它)。我想要 document.documentElement 获取视口的大小。

其次,我通过使用 AnimationPlayer 以编程方式定义动画 [而不是像我在上面尝试的那样在组件装饰器中定义它们] 解决了动态动画的问题。

我仍然很好奇是否可以通过组件装饰器中的动画 属性 动态更改动画...我希望一定有办法,但我一直很沮丧Angular 动画的手波浪感 API 仍然无法弄清楚。

此外,当在 'activated state' 中更改视口大小时,我的解决方案表现得很古怪(不响应调整大小 [如预期的那样] 并在其 'return' 开始时跳转动画到视口的新中间[再次如预期]。

这是我的解决方案的代码和 plunker

export class App implements OnInit {
  @ViewChild('myElement') myElement: ElementRef;
  activated: BehaviorSubject<string> = new BehaviorSubject<string>('dormant');
  transitionToActivated: any;
  player: AnimationPlayer;
  factory: any;

  constructor(private builder: AnimationBuilder) {}

  ngOnInit() {
    console.log('viewport width: ' + document.documentElement.clientWidth);
    console.log('viewport height: ' + document.documentElement.clientHeight);
    let rect = this.myElement.nativeElement.getBoundingClientRect();
    console.log('rect right: ' + rect.right);
    console.log('rect left: ' + rect.left);
    this.transitionToActivated = 'translateX(' + ((document.documentElement.clientWidth / 2) - 
        (rect.right + rect.left) / 2) + 'px) translateY(' + 
        ((document.documentElement.clientHeight / 2) - (rect.top + rect.bottom) / 2) + 
        'px) scale(1)';

    this.activated.subscribe(newValue => {
      this.transitionToActivated = 'translateX(' + ((document.documentElement.clientWidth / 2) - 
        (rect.right + rect.left) / 2) + 'px) translateY(' + 
        ((document.documentElement.clientHeight / 2) - (rect.top + rect.bottom) / 2) + 
        'px) scale(1)';
      console.log(this.transitionToActivated);
      if(newValue === 'activated'){
        this.factory = this.builder.build([
          style({ transform: 'translateX(0) translateY(0) scale(1)' }),
          animate(
            '1000ms', 
            style({ transform: this.transitionToActivated })
          )
        ]);
        this.player = this.factory.create(this.myElement.nativeElement, {});
        this.player.play()
      } else if(newValue === 'dormant'){
        this.factory = this.builder.build([
          style({ transform: this.transitionToActivated })
          animate(
            '1000ms', 
            style({ transform: 'translateX(0) translateY(0) scale(1)' }),
          )
        ]);
        this.player = this.factory.create(this.myElement.nativeElement, {});
        this.player.play()
      }
    })
  }
}