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()
}
})
}
}
我有一个通常处于休眠状态的组件(我只是说它对用户没什么兴趣),但在某种状态下这个组件变成 '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()
}
})
}
}