openaire-library/utils/section-scroll/section-scroll.component.ts

103 lines
2.9 KiB
TypeScript

import {AfterViewInit, Component, Input, ViewEncapsulation} from "@angular/core";
/**
* <section-scroll [customClass]="'optional classes for section e.g. uk-section-primary'"
* [childrenCustomClass]="'optional classes for content e.g. uk-container'">
* <div top>...</div>
* <div left>...</div>
* <div scroll>...</div>
* </section-scroll>
*
* */
@Component({
selector: 'section-scroll',
template: `
<div [ngClass]="customClass">
<ng-content select="[top]"></ng-content>
<div [ngClass]="childrenCustomClass">
<div class="uk-grid" uk-grid>
<ng-content select="[left]"></ng-content>
<ng-content select="[scroll]"></ng-content>
</div>
</div>
</div>
`,
styleUrls: ['section-scroll.component.css'],
encapsulation: ViewEncapsulation.None
})
export class SectionScrollComponent implements AfterViewInit {
@Input()
public customClass = null;
@Input()
public childrenCustomClass = null;
@Input()
public animationSteps: number = 20;
private observer: IntersectionObserver = null;
/**
* Define as keys the ids of elements in scroll section and as values the ids of left section
* */
@Input()
private map: Map<string, string> = null;
private left: Map<string, HTMLElement> = new Map<string, HTMLElement>();
private scroll: Map<string, HTMLElement> = new Map<string, HTMLElement>();
private lastElementId: string = null;
constructor() {
}
ngOnDestroy() {
if (this.observer) {
this.observer.disconnect();
}
}
ngAfterViewInit() {
if (typeof document !== "undefined" && this.map) {
this.createObserver();
}
}
createObserver() {
let observer;
let options = {
root: null,
rootMargin: "-20%",
threshold: this.buildThresholdList()
};
Array.from(this.map.values()).forEach(value => {
let element = document.getElementById(value);
this.left.set(value, element);
})
Array.from(this.map.keys()).forEach(key => {
this.scroll.set(key, document.getElementById(key));
})
observer = new IntersectionObserver(entries => {
entries.forEach((entry) => {
entry.target['style'].opacity = String(entry.intersectionRatio);
let id = this.map.get(entry.target.id);
if (this.left.has(id) && this.lastElementId !== id) {
if(entry.isIntersecting) {
this.lastElementId = id;
}
this.left.get(id).parentElement.style.opacity = String(entry.intersectionRatio);
}
});
}, options);
Array.from(this.scroll.values()).forEach(target => {
observer.observe(target)
});
}
buildThresholdList() {
let thresholds = [];
for (let i = 1.0; i <= this.animationSteps; i++) {
let ratio = i / this.animationSteps;
thresholds.push(ratio);
}
thresholds.push(0);
return thresholds;
}
}