import { DOCUMENT } from '@angular/common' ; import { Inject , Injectable } from '@angular/core' ; import { reqAnimFrame } from './request-animation' ; export type EasyingFn = ( t : number , b : number , c : number , d : number ) => number ; function easeInOutCubic ( t , b , c , d ) { const cc = c - b ; let tt = t / ( d / 2 ) ; if ( tt < 1 ) { return ( cc / 2 ) * tt * tt * tt + b ; } else { return ( cc / 2 ) * ( ( tt -= 2 ) * tt * tt + 2 ) + b ; } } @ Injectable ( { providedIn : 'root' } ) export class ThyScrollService { private document : Document ; constructor ( @ Inject ( DOCUMENT ) document ) { this . document = document ; } /** Set the position of the scroll bar of `element`. */ setScrollTop ( element , topValue = 0 ) { if ( element === window ) { this . document . body . scrollTop = topValue ; this . document . documentElement . scrollTop = topValue ; } else { ( element as Element ) . scrollTop = topValue ; } } /** Get the position of the scoll bar of `element`. */ getScroll ( element ? , top = true ) { const target = element ? element : window ; const prop = top ? 'pageYOffset' : 'pageXOffset' ; const method = top ? 'scrollTop' : 'scrollLeft' ; const isWindow = target === window ; let ret = isWindow ? target [ prop ] : target [ method ] ; if ( isWindow && typeof ret !== 'number' ) { ret = this . document . documentElement [ method ] ; } return ret ; } param container param topValue param easing param callback scrollTo ( container , topValue = 0 , easing ? , callback ? ) { const target = container ? container : window ; const scrollTop = this . getScroll ( target ) ; const startTime = Date . now ( ) ; const frameFunc = ( ) => { const timestamp = Date . now ( ) ; const time = timestamp - startTime ; this . setScrollTop ( target , ( easing || easeInOutCubic ) ( time , scrollTop , topValue , 450 ) ) ; if ( time < 450 ) { reqAnimFrame ( frameFunc ) ; } else { if ( callback ) { callback ( ) ; } } } ; reqAnimFrame ( frameFunc ) ; } }