可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I want a div to slide in from the right in angular 2 using css.
<div class="note" [ngClass]="{'transition':show}" *ngIf="show">
<p> Notes</p>
</div>
<button class="btn btn-default" (click)="toggle(show)">Toggle</button>
I works fine if i only use [ngClass] to toggle class and utilise opacity.
But li don't want that element to be rendered from the beginning so I "hide" it with ngIf first, but then the transition wont't work.
.transition{
-webkit-transition: opacity 1000ms ease-in-out,margin-left 500ms ease-in-out;
-moz-transition: opacity 1000ms ease-in-out,margin-left 500ms ease-in-out;
-ms-transition: opacity 1000ms ease-in-out,margin-left 500ms ease-in-out ;
-o-transition: opacity 1000ms ease-in-out,margin-left 500ms ease-in-out;
transition: opacity 1000ms ease-in-out,margin-left 500ms ease-in-out;
margin-left: 1500px;
width: 200px;
opacity: 0;
}
.transition{
opacity: 100;
margin-left: 0;
}
回答1:
update 4.1.0
Plunker
See also https://github.com/angular/angular/blob/master/CHANGELOG.md#400-rc1-2017-02-24
update 2.1.0
Plunker
For more details see Animations at angular.io
import { trigger, style, animate, transition } from '@angular/animations';
@Component({
selector: 'my-app',
animations: [
trigger(
'enterAnimation', [
transition(':enter', [
style({transform: 'translateX(100%)', opacity: 0}),
animate('500ms', style({transform: 'translateX(0)', opacity: 1}))
]),
transition(':leave', [
style({transform: 'translateX(0)', opacity: 1}),
animate('500ms', style({transform: 'translateX(100%)', opacity: 0}))
])
]
)
],
template: `
<button (click)="show = !show">toggle show ({{show}})</button>
<div *ngIf="show" [@enterAnimation]>xxx</div>
`
})
export class App {
show:boolean = false;
}
original
*ngIf
removes the element from the DOM when the expression becomes false
. You can't have a transition on a non-existing element.
Use instead hidden
:
<div class="note" [ngClass]="{'transition':show}" [hidden]="!show">
回答2:
According to the latest angular 2 documentation you can animate "Entering and Leaving" elements (like in angular 1).
Example of simple fade animation:
In relevant @Component add:
animations: [
trigger('fadeInOut', [
transition(':enter', [ // :enter is alias to 'void => *'
style({opacity:0}),
animate(500, style({opacity:1}))
]),
transition(':leave', [ // :leave is alias to '* => void'
animate(500, style({opacity:0}))
])
])
]
Do not forget to add imports
import {style, state, animate, transition, trigger} from '@angular/animations';
The relevant component's html's element should look like:
<div *ngIf="toggle" [@fadeInOut]>element</div>
I built example of slide and fade animation here.
Explanation on 'void' and '*':
void
is the state when ngIf
is set to false (it applies when the
element is not attached to a view).
*
- There can be many animation states (read more in docs). The *
state takes precedence over all of them as a "wildcard" (in my example this is the state when ngIf
is set to true
).
Notice (taken from angular docs):
Angular animations are built on top of the standard Web Animations API
and run natively on browsers that support it. For other browsers, a
polyfill is required. Grab web-animations.min.js from GitHub and add
it to your page.
回答3:
trigger('slideIn', [
state('*', style({ 'overflow-y': 'hidden' })),
state('void', style({ 'overflow-y': 'hidden' })),
transition('* => void', [
style({ height: '*' }),
animate(250, style({ height: 0 }))
]),
transition('void => *', [
style({ height: '0' }),
animate(250, style({ height: '*' }))
])
回答4:
CSS only solution for modern browsers
@keyframes slidein {
0% {margin-left:1500px;}
100% {margin-left:0px;}
}
.note {
animation-name: slidein;
animation-duration: .9s;
display: block;
}
回答5:
Am using angular 5 and for an ngif to work for me that is in a ngfor, I had to use animateChild and in the user-detail component I used the *ngIf="user.expanded" to show hide user and it worked for entering a leaving
<div *ngFor="let user of users" @flyInParent>
<ly-user-detail [user]= "user" @flyIn></user-detail>
</div>
//the animation file
export const FLIP_TRANSITION = [
trigger('flyInParent', [
transition(':enter, :leave', [
query('@*', animateChild())
])
]),
trigger('flyIn', [
state('void', style({width: '100%', height: '100%'})),
state('*', style({width: '100%', height: '100%'})),
transition(':enter', [
style({
transform: 'translateY(100%)',
position: 'fixed'
}),
animate('0.5s cubic-bezier(0.35, 0, 0.25, 1)', style({transform: 'translateY(0%)'}))
]),
transition(':leave', [
style({
transform: 'translateY(0%)',
position: 'fixed'
}),
animate('0.5s cubic-bezier(0.35, 0, 0.25, 1)', style({transform: 'translateY(100%)'}))
])
])
];
回答6:
One way is to use a setter for the ngIf property and set the state as part of updating the value. When setting the property to true detectChanges() needs to be called to make sure the element gets added back to the dom before the animation state gets changed.
StackBlitz example
example.component.ts
import { Component, AnimationTransitionEvent, OnInit } from '@angular/core';
import { trigger, state, style, animate, transition } from '@angular/animations';
@Component({
selector: 'example',
templateUrl: `./example.component.html`,
styleUrls: [`./example.component.css`],
animations: [
trigger('state', [
state('visible', style({
opacity: '1'
})),
state('hidden', style({
opacity: '0'
})),
transition('* => visible', [
animate('500ms ease-out')
]),
transition('visible => hidden', [
animate('500ms ease-out')
])
])
]
})
export class ExampleComponent implements OnInit {
state: string;
private _showButton: boolean;
get showButton() {
return this._showButton;
}
set showButton(val: boolean) {
if (val) {
this._showButton = true;
this.state = 'visible';
} else {
this.state = 'hidden';
}
}
constructor() {
}
ngOnInit() {
this.showButton = true;
}
animationDone(event: AnimationTransitionEvent) {
if (event.fromState === 'visible' && event.toState === 'hidden') {
this._showButton = false;
}
}
log() {
console.log('clicked');
}
}
example.component.html
<div>
<p>animation state: {{state}}</p>
<p>showButton: {{showButton}}</p>
<button (click)="showButton = !showButton">toggle</button>
</div>
<button class="animation-target" *ngIf="showButton" [@state]="state" (@state.done)="animationDone($event)" (click)="log()" >animation target</button>
example.component.css
.animation-target {
background: orange;
height: 150px;
width: 150px;
cursor: pointer;
opacity: 0;
}