@ -1,6 +1,6 @@
import { animate , keyframes , state , style , transition , trigger } from '@angular/animations' ;
import { NgStyle } from '@angular/common' ;
import { AfterViewInit , ChangeDetectorRef , Component , ContentChild , ElementRef , EventEmitter , Input , On Init, Output , QueryList , TemplateRef , ViewChild , ViewChildren } from '@angular/core' ;
import { AfterViewInit , ChangeDetectorRef , Component , ContentChild , ElementRef , EventEmitter , Input , On Changes, On Init, Output , QueryList , SimpleChanges , TemplateRef , ViewChild , ViewChildren } from '@angular/core' ;
import { BrowserModule } from '@angular/platform-browser' ;
import { AngularResizeEventModule , ResizedEvent } from 'angular-resize-event' ;
import { Subject , debounceTime } from 'rxjs' ;
@ -33,10 +33,9 @@ import { Subject, debounceTime } from 'rxjs';
] )
]
} )
export class CarouselComponent < T > implements OnInit , AfterViewInit {
export class CarouselComponent < T > implements OnInit , AfterViewInit , OnChanges {
@Output ( ) afterInitSelf : EventEmitter < CarouselComponent < T > > = new EventEmitter < CarouselComponent < T > > ( ) ;
@Output ( ) changedIndex : EventEmitter < number > = new EventEmitter < number > ( ) ;
@Input ( ) slides? : T [ ] ;
@ContentChild ( TemplateRef ) template? : TemplateRef < any > ;
@ViewChild ( 'carouselWindow' ) window ! : ElementRef ;
@ -45,6 +44,7 @@ export class CarouselComponent<T> implements OnInit, AfterViewInit {
@Input ( ) initIndex? : number ;
current : number = 0 ;
intersectionObserver? : IntersectionObserver ;
visibleSlides? : IntersectingSlide [ ] ;
increasing : boolean = true ;
@ -53,12 +53,10 @@ export class CarouselComponent<T> implements OnInit, AfterViewInit {
animation : string = 'vertical' ;
directionTime : number = 0 ;
@Input ( ) numVisible : number = 1 ;
@Input ( ) offset : number = 0 ;
containerDirectionLength : number = 0 ;
private debouncedOnchange : Subject < void > = new Subject < void > ( ) ;
constructor ( private cdr : ChangeDetectorRef ) {
this . visibleSlides = [ ] ;
this . debouncedOnchange . pipe ( debounceTime ( 500 ) ) . subscribe ( ( ) = > this . realOnChange ( ) ) ;
@ -67,9 +65,9 @@ export class CarouselComponent<T> implements OnInit, AfterViewInit {
}
}
ngOnInit ( ) : void {
this . afterInitSelf . next ( this ) ;
this . intersectionObserver = new IntersectionObserver ( ( entries , observer ) = > {
entries . forEach ( entry = > {
const runIntersectionHandling = ( ) = > {
@ -77,38 +75,35 @@ export class CarouselComponent<T> implements OnInit, AfterViewInit {
if ( ! entryIndex && entryIndex != 0 ) {
return ;
}
const entryIntersectingSlide = this . visibleSlides ? . find ( ( s ) = > {
return s . index == entryIndex ;
} ) ;
const entryIntersectingSlide = this . visibleSlides ? . find ( s = > s . index == entryIndex ) ;
if ( ! entryIntersectingSlide ) {
return ;
}
entryIntersectingSlide . currentlyIntersecting = entry . isIntersecting ;
if ( entryIntersectingSlide . hasBeenVisible && ! entry . isIntersecting ) {
this . visibleSlides = this . visibleSlides ? . filter ( e = > e . index != entryIndex ) ;
this . intersectionObserver ? . unobserve ( entry . target ) ;
}
} ;
runIntersectionHandling ( ) ;
this . onChange ( ) ;
} )
} )
}
numExtraNext() {
return Math . floor ( ( this . numVisible - 1 ) / 2 ) ;
return this . numVisible + this . offset - 1 ;
}
numExtraPrev() {
return Math . ceil ( ( this . numVisible - 1 ) / 2 ) ;
return 0 + this . offset ;
}
ngAfterViewInit ( ) : void {
ngOnChanges ( changes : SimpleChanges ) : void {
if ( changes [ 'numVisible' ] || changes [ 'offset' ] ) {
this . reinitializeVisibleSlides ( ) ;
}
}
ngAfterViewInit ( ) : void {
this . slideElements . changes . subscribe ( ( comps : QueryList < ElementRef > ) = > {
comps . forEach ( ( comp ) = > this . handleNewDomSlide ( comp ) )
} ) ;
@ -123,7 +118,6 @@ export class CarouselComponent<T> implements OnInit, AfterViewInit {
for ( let i = 0 ; i <= this . numExtraNext ( ) && i < this . slides ! . length ; i ++ ) {
this . visibleSlides ? . push ( {
index : i ,
hasBeenVisible : false ,
currentlyIntersecting : false ,
} )
}
@ -135,20 +129,19 @@ export class CarouselComponent<T> implements OnInit, AfterViewInit {
setIndex ( slideIndex : number ) {
this . current = slideIndex ;
console . log ( "setIndex" , slideIndex ) ;
this . visibleSlides! . length = 0 ;
console . log ( "length" , this . slides ! . length ) ;
this . reinitializeVisibleSlides ( ) ;
this . onChange( ) ;
}
for ( let i = - this . numExtraPrev ( ) ; i <= this . numExtraNext ( ) ; i ++ ) {
console . log ( "i, " , i ) ;
if ( this . current + i >= 0 && this . current + i < this . slides ! . length ) {
console . log ( "pushing" , this . current + i ) ;
reinitializeVisibleSlides() {
this . visibleSlides ! . length = 0 ;
const start = Math . max ( 0 , this . current - this . numExtraPrev ( ) ) ;
const end = Math . min ( this . current + this . numExtraNext ( ) , this . slides ! . length - 1 ) ;
for ( let i = start ; i <= end ; i ++ ) {
this . visibleSlides ? . push ( {
index : this.current + i ,
hasBeenVisible : false ,
index : i ,
currentlyIntersecting : false ,
} ) ;
}
}
this . onChange ( ) ;
@ -158,12 +151,10 @@ export class CarouselComponent<T> implements OnInit, AfterViewInit {
this . increasing = true ;
if ( this . slides && this . current + 1 < this . slides ? . length ) {
this . current += 1 ;
this . changedIndex . emit ( this . current ) ;
if ( this . current + this . numExtraNext ( ) < this . slides . length ) {
if ( ! this . visibleSlides ? . find ( e = > e . index == this . current + this . numExtraNext ( ) ) ) {
this . visibleSlides ? . push ( {
index : this.current + this . numExtraNext ( ) ,
hasBeenVisible : false ,
currentlyIntersecting : false ,
} ) ;
}
@ -176,13 +167,10 @@ export class CarouselComponent<T> implements OnInit, AfterViewInit {
this . increasing = false ;
if ( this . current - 1 >= 0 ) {
this . current -= 1 ;
this . changedIndex . emit ( this . current ) ;
if ( this . current - this . numExtraPrev ( ) >= 0 ) {
if ( ! this . visibleSlides ? . find ( e = > e . index == this . current - this . numExtraPrev ( ) ) ) {
this . visibleSlides ? . push ( {
index : this.current - this . numExtraPrev ( ) ,
hasBeenVisible : false ,
currentlyIntersecting : false ,
} ) ;
}
@ -196,47 +184,36 @@ export class CarouselComponent<T> implements OnInit, AfterViewInit {
}
realOnChange() {
const safetyFactor = this . numVisible == 1 ? 1 : 2 ;
{
const intersecting = this . visibleSlides ? . filter ( e = > e . currentlyIntersecting ) . sort ( ( e1 , e2 ) = > e1 . index - e2 . index ) ;
if ( intersecting && intersecting . length > 0 ) {
const lowestIntersecting = intersecting ! [ 0 ] ;
this . visibleSlides = this . visibleSlides ? . filter ( e = > e . index + safetyFactor >= lowestIntersecting ! . index && e . index >= this . current - this . numExtraPrev ( ) ) ;
}
}
{
const safetyFactor = ( this . numVisible == 1 ? 1 : 2 ) ;
const intersecting = this . visibleSlides ? . filter ( e = > e . currentlyIntersecting ) . sort ( ( e1 , e2 ) = > e1 . index - e2 . index ) ;
if ( intersecting && intersecting . length > 0 ) {
const lowestIntersecting = intersecting ! [ 0 ] ;
const highestIntersecting = intersecting ! [ intersecting ! . length - 1 ] ;
const intersecting = this . visibleSlides ? . filter ( e = > e . currentlyIntersecting ) . sort ( ( e1 , e2 ) = > e1 . index - e2 . index ) . reverse ( ) ;
if ( intersecting && intersecting . length > 0 ) {
const highestIntersecting = intersecting ! [ 0 ]
this . visibleSlides = this . visibleSlides ? . filter ( e = > e . index - safetyFactor <= highestIntersecting ! . index && e . index <= this . current + this . numExtraNext ( ) ) ;
}
const min = Math . min ( lowestIntersecting . index - safetyFactor , this . current - this . numExtraPrev ( ) ) ;
const max = Math . max ( highestIntersecting . index + safetyFactor , this . current + this . numExtraNext ( ) ) ;
this . visibleSlides = this . visibleSlides ? . filter ( e = > e . index >= min && e . index <= max ) ;
}
}
translation() {
let num = ( this . current - this . numExtraNext ( ) - ( this . numVisible % 2 == 0 ? 1 : 0 ) ) * ( - 1 / this . numVisible ) * 100 ;
const step = this . containerDirectionLength / this . numVisible ;
const pos = ( this . current - this . numExtraNext ( ) - ( this . numVisible % 2 == 0 ? 1 : 0 ) ) ;
const offset = pos * - step ;
const translation = - ( ( this . current - this . offset ) * step ) ;
if ( this . vertical ) {
return ` 0 ${ offset } px `
return ` 0 ${ translation } px `
} else {
return ` ${ offset } px 0 `
return ` ${ translation } px 0 `
}
}
templateValue() {
const len = this . slides ? . length ;
return ` repeat( ${ len } , ${ this . containerDirectionLength / this . numVisible } px) ` ;
}
style() {
let style : any = {
} ;
let style : any = { } ;
if ( this . vertical ) {
style [ 'grid-template-rows' ] = this . templateValue ( ) ;
@ -281,11 +258,9 @@ export class CarouselComponent<T> implements OnInit, AfterViewInit {
this . containerDirectionLength = event . newRect . width ;
}
}
}
interface IntersectingSlide {
index : number ;
hasBeenVisible : boolean ;
currentlyIntersecting : boolean ;
}