UNPKG

1.89 kBJavaScriptView Raw
1function scrollDir() {
2 const el = document.documentElement;
3 const win = window;
4 const attribute = 'data-scrolldir';
5 const body = document.body;
6 const historyLength = 32; // Ticks to keep in history.
7 const historyMaxAge = 512; // History data time-to-live (ms).
8 const thresholdPixels = 64; // Ignore moves smaller than this.
9 const history = Array(historyLength);
10 let dir = 'down'; // 'up' or 'down'
11 let e; // last scroll event
12 let pivot; // "high-water mark"
13 let pivotTime = 0;
14
15 const tick = function tickFunc() {
16 let y = win.scrollY;
17 const t = e.timeStamp;
18 const furthest = dir === 'down' ? Math.max : Math.min;
19
20 // Apply bounds to handle rubber banding
21 const yMax = body.offsetHeight - win.innerHeight;
22 y = Math.max(0, y);
23 y = Math.min(yMax, y);
24
25 // Update history
26 history.unshift({ y, t });
27 history.pop();
28
29 // Are we continuing in the same direction?
30 if (y === furthest(pivot, y)) {
31 // Update "high-water mark" for current direction
32 pivotTime = t;
33 pivot = y;
34 return;
35 }
36 // else we have backed off high-water mark
37
38 // Apply max age to find current reference point
39 const cutoffTime = t - historyMaxAge;
40 if (cutoffTime > pivotTime) {
41 pivot = y;
42 for (let i = 0; i < historyLength; i += 1) {
43 if (!history[i] || history[i].t < cutoffTime) break;
44 pivot = furthest(pivot, history[i].y);
45 }
46 }
47
48 // Have we exceeded threshold?
49 if (Math.abs(y - pivot) > thresholdPixels) {
50 pivot = y;
51 pivotTime = t;
52 dir = dir === 'down' ? 'up' : 'down';
53 el.setAttribute(attribute, dir);
54 }
55 };
56
57 const handler = function handlerFunc(event) {
58 e = event;
59 win.requestAnimationFrame(tick);
60 };
61
62 pivot = win.scrollY;
63 el.setAttribute(attribute, dir);
64 return win.addEventListener('scroll', handler);
65}
66scrollDir();