1
+ // animateScroll.ts
1
2
import { cubicInOut } from 'svelte/easing' ;
2
- import { loop , noop , now } from 'svelte/internal' ;
3
- import { ScrollToElementOptions } from '../global.interface' ;
4
- import { $ , cumulativeOffset , extend , scrollLeft , scrollTop } from '../helpers/helper.js' ;
3
+ import { $ , cumulativeOffset , extend , noop , scrollLeft , scrollTop , startAnimationLoop } from '../helpers/helper.js' ;
4
+ import { ScrollToElementOptions } from './../global.interface.js' ;
5
5
6
+ // Default options
6
7
const defaultOptions : ScrollToElementOptions = {
7
8
container : 'body' ,
8
9
duration : 500 ,
@@ -16,26 +17,14 @@ const defaultOptions: ScrollToElementOptions = {
16
17
scrollY : true
17
18
} ;
18
19
20
+ // Scroll to internal implementation
19
21
const scrollToInternal = ( options : ScrollToElementOptions ) : ( ( ) => void ) => {
20
- const {
21
- duration,
22
- delay,
23
- easing,
24
- x = 0 ,
25
- y = 0 ,
26
- scrollX,
27
- scrollY,
28
- onStart,
29
- onDone,
30
- container,
31
- onAborting,
32
- element
33
- } = options ;
22
+ const { duration, delay, easing, x = 0 , y = 0 , scrollX, scrollY, onStart, onDone, onAborting, container, element } = options ;
34
23
35
24
let { offset } = options ;
36
25
37
26
if ( typeof offset === 'function' ) {
38
- offset = offset ( ) as Function ;
27
+ offset = offset ( ) as number ;
39
28
}
40
29
41
30
const cumulativeOffsetContainer = cumulativeOffset ( container ) ;
@@ -52,32 +41,32 @@ const scrollToInternal = (options: ScrollToElementOptions): (() => void) => {
52
41
53
42
let scrolling = true ;
54
43
let started = false ;
55
- const startTime = now ( ) + delay ;
44
+ const startTime = performance . now ( ) + delay ;
56
45
const endTime = startTime + duration ;
57
46
58
- function scrollToTopLeft ( element : HTMLElement , top : number , left : number ) : void {
59
- if ( scrollX ) scrollLeft ( element , left ) ;
60
- if ( scrollY ) scrollTop ( element , top ) ;
61
- }
47
+ const scrollToTopLeft = ( el : HTMLElement , top : number , left : number ) : void => {
48
+ if ( scrollX ) scrollLeft ( el , left ) ;
49
+ if ( scrollY ) scrollTop ( el , top ) ;
50
+ } ;
62
51
63
- function start ( delayStart : number | boolean ) : void {
64
- if ( ! delayStart ) {
52
+ const start = ( ) => {
53
+ if ( ! started ) {
65
54
started = true ;
66
55
onStart ( element , { x, y } ) ;
67
56
}
68
- }
57
+ } ;
69
58
70
- function tick ( progress : number ) : void {
59
+ const tick = ( progress : number ) => {
71
60
scrollToTopLeft ( container , initialY + diffY * progress , initialX + diffX * progress ) ;
72
- }
61
+ } ;
73
62
74
- function stop ( ) : void {
63
+ const stop = ( ) => {
75
64
scrolling = false ;
76
- }
65
+ } ;
77
66
78
- loop ( ( now ) : boolean => {
67
+ startAnimationLoop ( ( now ) => {
79
68
if ( ! started && now >= startTime ) {
80
- start ( false ) ;
69
+ start ( ) ;
81
70
}
82
71
83
72
if ( started && now >= endTime ) {
@@ -90,22 +79,22 @@ const scrollToInternal = (options: ScrollToElementOptions): (() => void) => {
90
79
onAborting ( element , { x, y } ) ;
91
80
return false ;
92
81
}
82
+
93
83
if ( started ) {
94
- const p = now - startTime ;
95
- const t = 0 + 1 * easing ( p / duration ) ;
84
+ const p = ( now - startTime ) / duration ;
85
+ const t = easing ( p ) ;
96
86
tick ( t ) ;
97
87
}
98
88
99
- return true ;
89
+ return scrolling ;
100
90
} ) ;
101
91
102
- start ( delay ) ;
103
-
104
- tick ( 0 ) ;
92
+ tick ( 0 ) ; // Initial tick
105
93
106
94
return stop ;
107
95
} ;
108
96
97
+ // Helper functions
109
98
const proceedOptions = ( options : ScrollToElementOptions ) : ScrollToElementOptions => {
110
99
const opts = extend ( { } , defaultOptions , options ) ;
111
100
opts . container = $ ( opts . container ) ;
@@ -115,76 +104,71 @@ const proceedOptions = (options: ScrollToElementOptions): ScrollToElementOptions
115
104
116
105
const scrollContainerHeight = ( containerElement : HTMLElement | Document ) : number => {
117
106
if ( containerElement && containerElement !== document && containerElement !== document . body ) {
118
- return (
119
- ( containerElement as HTMLElement ) . scrollHeight -
120
- ( containerElement as HTMLElement ) . offsetHeight
121
- ) ;
107
+ return ( containerElement as HTMLElement ) . scrollHeight - ( containerElement as HTMLElement ) . offsetHeight ;
122
108
}
123
109
const { body } = document ;
124
110
const html = document . documentElement ;
125
111
126
- return Math . max (
127
- body . scrollHeight ,
128
- body . offsetHeight ,
129
- html . clientHeight ,
130
- html . scrollHeight ,
131
- html . offsetHeight
132
- ) ;
112
+ return Math . max ( body . scrollHeight , body . offsetHeight , html . clientHeight , html . scrollHeight , html . offsetHeight ) ;
133
113
} ;
134
114
135
115
const setGlobalOptions = ( options : ScrollToElementOptions ) : void => {
136
116
extend ( defaultOptions , options || { } ) ;
137
117
} ;
138
118
139
- const scrollTo = ( options : ScrollToElementOptions ) : ( ( ) => void ) =>
140
- scrollToInternal ( proceedOptions ( options ) ) ;
119
+ // Scroll functions
120
+ const scrollTo = ( options : ScrollToElementOptions ) : ( ( ) => void ) => scrollToInternal ( proceedOptions ( options ) ) ;
141
121
142
122
const scrollToBottom = ( options ?: ScrollToElementOptions ) : ( ( ) => void ) => {
143
- options = proceedOptions ( options ) ;
123
+ const opts = proceedOptions ( options ) ;
144
124
145
125
return scrollToInternal (
146
- extend ( options , {
126
+ extend ( opts , {
147
127
element : null ,
148
- y : scrollContainerHeight ( options . container )
128
+ y : scrollContainerHeight ( opts . container )
149
129
} )
150
130
) ;
151
131
} ;
152
132
153
133
const scrollToTop = ( options ?: ScrollToElementOptions ) : ( ( ) => void ) => {
154
- options = proceedOptions ( options ) ;
134
+ const opts = proceedOptions ( options ) ;
155
135
156
136
return scrollToInternal (
157
- extend ( options , {
137
+ extend ( opts , {
158
138
element : null ,
159
139
y : 0
160
140
} )
161
141
) ;
162
142
} ;
163
143
164
- const makeScrollToAction =
165
- ( scrollToFunc : Function ) => ( node : Node , options : ScrollToElementOptions ) => {
166
- let current = options ;
167
- const handle : EventListenerOrEventListenerObject = ( e : Event ) => {
168
- e . preventDefault ( ) ;
169
- scrollToFunc ( typeof current === 'string' ? { element : current } : current ) ;
170
- } ;
171
- node . addEventListener ( 'click' , handle ) ;
172
- node . addEventListener ( 'touchstart' , handle ) ;
173
- return {
174
- update ( options : ScrollToElementOptions ) : void {
175
- current = options ;
176
- } ,
177
- destroy ( ) : void {
178
- node . removeEventListener ( 'click' , handle ) ;
179
- node . removeEventListener ( 'touchstart' , handle ) ;
180
- }
181
- } ;
144
+ const makeScrollToAction = ( scrollToFunc : Function ) => ( node : Node , options : ScrollToElementOptions ) => {
145
+ let current = options ;
146
+ const handle : EventListenerOrEventListenerObject = ( e : Event ) => {
147
+ e . preventDefault ( ) ;
148
+ scrollToFunc ( typeof current === 'string' ? { element : current } : current ) ;
182
149
} ;
150
+ node . addEventListener ( 'click' , handle ) ;
151
+ node . addEventListener ( 'touchstart' , handle ) ;
152
+ return {
153
+ update ( options : ScrollToElementOptions ) : void {
154
+ current = options ;
155
+ } ,
156
+ destroy ( ) : void {
157
+ node . removeEventListener ( 'click' , handle ) ;
158
+ node . removeEventListener ( 'touchstart' , handle ) ;
159
+ }
160
+ } ;
161
+ } ;
183
162
184
163
// Actions
185
164
export const scrollto = makeScrollToAction ( scrollTo ) ;
186
165
export const scrolltotop = makeScrollToAction ( scrollToTop ) ;
187
166
export const scrolltobottom = makeScrollToAction ( scrollToBottom ) ;
188
167
189
168
// Methods
190
- export const animateScroll = { scrollTo, scrollToTop, scrollToBottom, setGlobalOptions } ;
169
+ export const animateScroll = {
170
+ scrollTo,
171
+ scrollToTop,
172
+ scrollToBottom,
173
+ setGlobalOptions
174
+ } ;
0 commit comments