角度动画 - 动态和响应式翻译

时间:2018-01-24 11:43:16

标签: angular5 angular-animations

我有一个通常处于休眠状态的组件(我只是意味着它对用户不感兴趣),但在某种状态下,这个组件变为“激活”,我想把它放在确切的中心位置。屏幕并放大以吸引用户的注意力。

这些组件中有几个处于休眠状态,但只有1个被激活。休眠组件可以在屏幕上的任何位置,因此我想要一个解决方案,将组件从原来的任何位置转换到屏幕中间,同时激活,然后在完成后将其返回到其原始休眠位置。

试图这样做:

模板:

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

我的语法是关闭的:组件装饰器内部的$ transitionToActivated无效。这种具有角动画的响应式动画是否可能?或者我需要研究纯CSS解决方案吗?

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

1 个答案:

答案 0 :(得分:0)

我想出了几件事。

首先,我正在使用window.screen来查看“屏幕”的宽度和高度。这实际上是给我监视器的分辨率(调整窗口大小不会影响它)。我希望document.documentElement获取视口的大小。

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

我仍然很好奇动画是否可以通过组件装饰器内部的动画属性动态改变...我希望必须有一种方法,但是我对手工波浪感到非常沮丧Angular动画API仍然无法弄明白。

此外,当视口大小在“激活状态”下更改时,我的解决方案会变得很复杂(不响应调整大小[正如预期]并在其“返回”动画开始时跳转到新中间视口[再次如预期]。

这是我的解决方案的代码和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()
      }
    })
  }
}