J'ai créé un composant de base qui fournit un indicateur appearOnce, qui devient vrai une fois si le composant est complètement dans la vue ou si son bord supérieur a atteint le bord supérieur de la vue.
@Injectable()
export class AppearOnce implements AfterViewInit, OnDestroy {
appearedOnce: boolean;
elementPos: number;
elementHeight: number;
scrollPos: number;
windowHeight: number;
subscriptionScroll: Subscription;
subscriptionResize: Subscription;
constructor(private element: ElementRef, private cdRef: ChangeDetectorRef){}
onResize() {
this.elementPos = this.getOffsetTop(this.element.nativeElement);
this.elementHeight = this.element.nativeElement.clientHeight;
this.checkVisibility();
}
onScroll() {
this.scrollPos = window.scrollY;
this.windowHeight = window.innerHeight;
this.checkVisibility();
}
getOffsetTop(element: any){
let offsetTop = element.offsetTop || 0;
if(element.offsetParent){
offsetTop += this.getOffsetTop(element.offsetParent);
}
return offsetTop;
}
checkVisibility(){
if(!this.appearedOnce){
if(this.scrollPos >= this.elementPos || (this.scrollPos + this.windowHeight) >= (this.elementPos + this.elementHeight)){
this.appearedOnce = true;
this.unsubscribe();
this.cdRef.detectChanges();
}
}
}
subscribe(){
this.subscriptionScroll = Observable.fromEvent(window, 'scroll').startWith(null)
.subscribe(() => this.onScroll());
this.subscriptionResize = Observable.fromEvent(window, 'resize').startWith(null)
.subscribe(() => this.onResize());
}
unsubscribe(){
if(this.subscriptionScroll){
this.subscriptionScroll.unsubscribe();
}
if(this.subscriptionResize){
this.subscriptionResize.unsubscribe();
}
}
ngAfterViewInit(){
this.subscribe();
}
ngOnDestroy(){
this.unsubscribe();
}
}
Vous pouvez simplement étendre ce composant et utiliser la appearedOnce propriété par héritage
@Component({
template: `
<div>
<div *ngIf="appearedOnce">...</div>
...
</div>
`
})
class MyComponent extends AppearOnceComponent {
...
}
Gardez à l'esprit pour appeler super() si vous avez besoin d'écraser le constructeur ou lifecyclehooks.
(modifier) plunker: https://embed.plnkr.co/yIpA1mI1b9kVoEXGy6Hh/
(modifier) Je l'ai transformé cela en une directive dans une autre réponse ci-dessous.
Je ne sais pas, mais ce lien peut être utile https://angular.io /docs/ts/latest/guide/animations.html#!#parallel-animation-groups? – sandyJoshi
Salut Sandy, j'ai jeté un coup d'œil à ça et l'approche des groupes d'animation parallèles aide les animations en chaîne mais il ne semble pas possible de se déclencher quand un div entre dans le point de vue. un temps variable lorsque l'utilisateur décide de faire défiler jusqu'à la div. Connaissez-vous une solution à ce comportement de l'interface utilisateur? – Ultronn