Я хочу добавить несколько вертикально сложенных компонентов (каждый из которых является языком программирования, app-skill ) по мере их появления в окне просмотра.Моя проблема заключается в том, что когда первый компонент входит в область просмотра, он корректно появляется, но также исчезает и все остальные компоненты под ним, и я хочу, чтобы остальные компоненты отображались ТОЛЬКО в том виде, в котором они появляются в области просмотра.
skill.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>
skill.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 .
emerge-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);
// /281803/opredelite-perekryvaytsya-li-dva-diapazona-dat
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
in onAppear()
Я только изменяю значение переменной visibility
с hide на show . Это запускает соответствующую анимацию [@visibilityState]
во всех компонентах (навыках), но непросто единственное внутри окна просмотра, что я и хочу.
Любая помощь будет признательна