import { AfterContentInit, ChangeDetectorRef, Component, ContentChildren, ElementRef, Input, OnDestroy, OnInit, QueryList } from "@angular/core"; import {SliderColumnComponent} from "./slider-column.component"; export class Stage { value: number; max: number; } @Component({ selector: 'slider-container', template: `
` }) export class SliderContainerComponent implements OnInit, OnDestroy, AfterContentInit { private static INTERVAL = 10; private static ANIMATION_DURATION = 600; // UIKit progress animation duration @ContentChildren(SliderColumnComponent) sliders: QueryList; @Input() navigation: 'progress' | null = null; @Input() total: number = 0; @Input() period: number = 3000; // in ms (>= 1000ms) @Input() infinite: boolean = false; @Input() parent: HTMLDivElement; stages: Stage[] = []; time: number = 0; interval: any; observer: IntersectionObserver; initialized: boolean = false; stopped: boolean = true; constructor(private cdr: ChangeDetectorRef, private element: ElementRef) { } ngOnInit() { this.period = this.period - SliderContainerComponent.ANIMATION_DURATION; } ngOnDestroy() { if(this.observer && typeof IntersectionObserver !== 'undefined') { this.observer.disconnect(); } } ngAfterContentInit() { this.setObserver(); this.sliders.forEach(slider => { slider.setContainer(this); slider.navItems.forEach(item => { if(this.parent) { item.background = getComputedStyle(this.parent).backgroundColor; } }); }); } setObserver() { if(typeof IntersectionObserver !== 'undefined') { let options = { root: null, rootMargin: '0px', threshold: 0.1 }; this.observer = new IntersectionObserver(entries => { entries.forEach(entry => { if (entry.isIntersecting && !this.initialized) { this.stopped = false; this.start(0); this.initialized = true; } else { this.initialized = false; this.stopped = true; } }); }, options); this.observer.observe(this.element.nativeElement); } } start(time: number) { this.stages = []; for(let i = 0; i < this.total; i++) { this.stages.push({value: (time > i?this.period:(time - i)), max: this.period}); } if(this.interval) { clearInterval(this.interval); } this.cdr.detectChanges(); this.interval = setInterval(() => { let current = Math.floor(time); this.stages[current].value += SliderContainerComponent.INTERVAL; this.time = current + this.stages[current].value/this.stages[current].max; this.sliders.forEach(slider => { slider.change(this.time); }); if(this.stages[current].value >= this.stages[current].max) { clearInterval(this.interval); let next = (current + 1 > this.total - 1)?0:current + 1; if(!this.stopped && (this.infinite || next > current)) { setTimeout(() => { this.start(next); }, SliderContainerComponent.ANIMATION_DURATION); } } }, SliderContainerComponent.INTERVAL); } }