import { EventEmitter } from '@angular/core' ; import { fromEvent , Observable } from 'rxjs' ; import { debounceTime , throttleTime } from 'rxjs/operators' ; export class ScrollService { scroll : Observable < Event > ; view : any ; viewListener ; viewEmitter : EventEmitter < any > = new EventEmitter ( ) ; static _ ( ) { return new ScrollService ( ) ; } constructor ( ) { this . view = document . getElementsByTagName ( 'body' ) [ 0 ] ; this . view . scrollTop = 0 ; this . scroll = fromEvent ( window , 'scroll' ) ; } listen ( callback , debounce = 0 , throttle = 0 ) { if ( debounce ) { return this . scroll . pipe ( debounceTime ( debounce ) ) . subscribe ( callback ) ; } if ( throttle ) { return this . scroll . pipe ( throttleTime ( throttle ) ) . subscribe ( callback ) ; } return this . scroll . subscribe ( callback ) ; } unListen ( subscription ) { subscription . unsubscribe ( ) ; } listenForView ( ) { if ( ! this . viewListener ) { this . viewListener = this . scroll . pipe ( debounceTime ( 100 ) ) . subscribe ( e => { this . viewEmitter . next ( e ) ; } ) ; } return this . viewEmitter ; } isVisible ( element , topTolerance = 0 ) { const vpTop = this . view . scrollTop ; const vpBottom = vpTop + this . view . clientHeight ; const vpHeight = vpBottom - vpTop ; const elBounds = element . getBoundingClientRect ( ) ; const elTop = elBounds . top - topTolerance ; const elBottom = elTop + elBounds . height ; const vpEl = elTop - vpHeight ; if ( elBottom > 0 && vpEl < 0 ) { return true ; } return false ; } }