import { Directive , Injectable , Input , ElementRef , Renderer2 , OnInit , AfterViewInit , OnDestroy } from '@angular/core' ; import { ScrollSpyService } from '../core/service' ; export interface ScrollSpyParallaxOptions { spyId ? : string ; horizontal ? : boolean ; cssKey ? : string ; property ? : string ; ratio ? : number ; initValue ? : number ; max ? : number ; min ? : number ; unit ? : string ; axis ? : string ; } @ Injectable ( ) @ Directive ( { selector : '[scrollSpyParallax]' } ) export class ScrollSpyParallaxDirective implements OnInit , AfterViewInit , OnDestroy { @ Input ( 'scrollSpyParallax' ) public options : ScrollSpyParallaxOptions ; @ Input ( ) public scrollSpyParallaxDisabled : boolean ; public cssValue : string ; public isSpecialVal : boolean = false ; public defaultOptions : ScrollSpyParallaxOptions = { spyId : 'window' , horizontal : false , cssKey : 'backgroundPosition' , property : 'backgroundPositionY' , ratio : - .7 , initValue : 0 , unit : 'px' , axis : 'Y' } ; public scrollStream$ : any ; public el : HTMLElement ; constructor ( private renderer , private elRef , private scrollSpy ) { this . el = elRef . nativeElement ; } ngOnInit ( ) { if ( ! this . options ) { this . options = { } ; } this . options = Object . assign ( this . defaultOptions , this . options ) ; if ( this . scrollSpyParallaxDisabled === undefined ) { this . scrollSpyParallaxDisabled = false ; } if ( this . options . property . match ( /backgroundPosition/i ) ) { if ( this . options . property . split ( 'backgroundPosition' ) [ 1 ] . toUpperCase ( ) === 'X' ) { this . options . axis = 'X' ; } this . options . property = 'backgroundPosition' ; } let cssValArray ; cssValArray = this . options . property . split ( ':' ) ; this . options . cssKey = cssValArray [ 0 ] ; this . cssValue = cssValArray [ 1 ] ; this . isSpecialVal = this . cssValue ? true : false ; if ( ! this . cssValue ) { this . cssValue = this . options . cssKey ; } this . options . ratio = + this . options . ratio ; this . options . initValue = + this . options . initValue ; } ngAfterViewInit ( ) { if ( ! ! this . scrollSpy . getObservable ( this . options . spyId ) ) { this . scrollStream$ = this . scrollSpy . getObservable ( this . options . spyId ) . subscribe ( ( e ) => { if ( ! this . scrollSpyParallaxDisabled ) { this . evaluateScroll ( e . target ) ; } } ) ; } else { return console . warn ( 'ScrollSpyParallax: No ScrollSpy observable for id "' + this . options . spyId + '"' ) ; } } evaluateScroll ( target ) { let currentScrollPosition ; if ( typeof target . scrollTop !== 'undefined' ) { currentScrollPosition = target . scrollTop ; } else if ( typeof target . scrollingElement !== 'undefined' ) { currentScrollPosition = target . scrollingElement . scrollTop ; } else if ( typeof target . scrollY !== 'undefined' ) { currentScrollPosition = target . scrollY ; } else if ( typeof target . pageYOffset !== 'undefined' ) { currentScrollPosition = target . pageYOffset ; } else if ( target . parentWindow && target . parentWindow . pageYOffset ) { currentScrollPosition = target . parentWindow . pageYOffset ; } let result ; let value ; value = currentScrollPosition * this . options . ratio + this . options . initValue ; if ( this . options . max !== undefined && currentScrollPosition >= this . options . max ) { currentScrollPosition = this . options . max ; } else if ( this . options . min !== undefined && currentScrollPosition <= this . options . min ) { currentScrollPosition = this . options . min ; } if ( this . options . cssKey === 'backgroundPosition' ) { if ( this . options . axis === 'X' ) { result = value + this . options . unit + ' 0' ; } else { result = '0 ' + value + this . options . unit ; } } else if ( this . isSpecialVal ) { result = this . cssValue + '(' + value + this . options . unit + ')' ; } else { result = value + this . options . unit ; } this . renderer . setStyle ( this . el , this . options . cssKey , result ) ; } ngOnDestroy ( ) { this . scrollStream$ . unsubscribe ( ) ; } }