Angular 2+,淡入视口中的多个组件

时间:2019-02-20 17:33:35

标签: angular angular-directive angular-animations

我想淡入显示在视口中的多个垂直堆叠的组件(每个组件都是一种编程语言, app-skill )。我的问题是,当第一个组件进入视口时,它会正确淡入,但也会淡入他下面的所有其余组件,并且我希望其余组件仅在它们出现在视口中时才具有动画效果。

skills.component.html

<section class="skills">
  <div class="heading__grid">
    <h1 class="heading__grid-title">My Skills</h1>
    <div class="heading__grid-underline"></div>
  </div>

  <div class="skills__grid">

    <app-skill
        (appear)="onAppear()"
        [@visibilityState]="visibility"
        *ngFor="let skill of skills; index as i"
        [skill]="skill"
        [i]="i"
        >

  </app-skill>

  </div>
</section>

skills.component.ts

import { Component, OnInit } from '@angular/core';

import { Skill } from './skill.model';
import { visibilityStateTrigger } from './animations';

@Component({
  selector: 'app-skills',
  templateUrl: './skills.component.html',
  styleUrls: ['./skills.component.scss'],
  animations: [visibilityStateTrigger]
})
export class SkillsComponent implements OnInit {
  visibility: string = 'hide';

  skills: Skill[] = [
    new Skill('JavaScript', '65%'),
    new Skill('HTML', '70%'),
    new Skill('CSS', '70%'),
    new Skill('React', '60%'),
    new Skill('Angular 2+', '40%'),
    new Skill('Git', '60%'),
    new Skill('Java', '70%'),
    new Skill('SQL', '80%'),
    new Skill('SASS', '55%')
  ];

   ngOnInit() {}

  onAppear() {
    console.log('onAppear fired');
    this.visibility = 'show';

  }
}

指令为(appear),它触发onAppear()方法,该方法将变量可见性从 hide 更改为 show

appear-skill.directive.ts

import { Directive, ElementRef, HostListener, EventEmitter, Output } from '@angular/core';


@Directive({
    selector: '[appear]'
})
export class AppearSkillDirective {
    fired: boolean = false;
    @Output() appear: EventEmitter<void> = new EventEmitter<any>();
    constructor(public el: ElementRef) {}

    @HostListener('window: scroll') inViewport() {

        if ( !this.fired && this.isAnyPartOfElementInViewport(this.el)  ) {
             console.log('inside view port');
             this.fired = true;
             this.appear.emit();
         }

    }

    isAnyPartOfElementInViewport(el: ElementRef ) {

    const rect = el.nativeElement.getBoundingClientRect();
    // DOMRect { x: 8, y: 8, width: 100, height: 100, top: 8, right: 108, bottom: 108, left: 8 }
    const windowHeight = (window.innerHeight || document.documentElement.clientHeight);
    const windowWidth = (window.innerWidth || document.documentElement.clientWidth);

    // http://stackoverflow.com/questions/325933/determine-whether-two-date-ranges-overlap
    const vertInView = (rect.top <= windowHeight) && ((rect.top + rect.height) >= 0);
    const horInView = (rect.left <= windowWidth) && ((rect.left + rect.width) >= 0);

    return (vertInView && horInView);
}

}

这是animation.ts文件

import { trigger, state, style, animate, transition } from 

'@angular/animations';

export const visibilityStateTrigger = trigger('visibilityState', [
    state('shown', style({
        opacity: 1
    })),
    state('hide', style({
        opacity: 0
    })),
    transition('show => hide', animate('2s') ),
    transition('hide => show', animate('2s') )
])

正如您在skills.components.ts中的onAppear()中所看到的,我仅将变量visibility的值从 hide 更改为 show 。这会在所有组件(技能)中运行相应的动画[@visibilityState],而不仅仅是我想要的视口中的唯一动画。
任何帮助将不胜感激

0 个答案:

没有答案