/
ScrollListener.js
60 lines (53 loc) · 1.35 KB
/
ScrollListener.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/**
* The `ScrollListener` class sets up a listener that handles window scroll
* events.
*/
export default class ScrollListener {
/**
* @param {(top: number) => void} callback The callback to run when the scroll position
* changes.
*/
constructor(callback) {
this.callback = callback;
this.ticking = false;
}
/**
* On each animation frame, as long as the listener is active, run the
* `update` method.
*
* @protected
*/
loop() {
// THROTTLE: If the callback is still running (or hasn't yet run), we ignore
// further scroll events.
if (this.ticking) return;
// Schedule the callback to be executed soon (TM), and stop throttling once
// the callback is done.
requestAnimationFrame(() => {
this.update();
this.ticking = false;
});
this.ticking = true;
}
/**
* Run the callback, whether there was a scroll event or not.
*/
update() {
this.callback(window.pageYOffset);
}
/**
* Start listening to and handling the window's scroll position.
*/
start() {
if (!this.active) {
window.addEventListener('scroll', (this.active = this.loop.bind(this)), { passive: true });
}
}
/**
* Stop listening to and handling the window's scroll position.
*/
stop() {
window.removeEventListener('scroll', this.active);
this.active = null;
}
}