forked from nodejs/nodejs.dev
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscrollTo.tsx
More file actions
70 lines (64 loc) · 1.82 KB
/
scrollTo.tsx
File metadata and controls
70 lines (64 loc) · 1.82 KB
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
61
62
63
64
65
66
67
68
69
70
import { isMobileScreen } from './isScreenWithinWidth';
const easeInOutCubic = (t: number, b: number, c: number, d: number) =>
(t /= d / 2) < 1
? (c / 2) * t * t * t + b
: (c / 2) * ((t -= 2) * t * t + 2) + b;
export function scrollTo(
scrollTo: number,
element: HTMLElement | null = null,
duration: number = 333
): Promise<boolean> {
const start =
((element && element.scrollTop) ||
window.pageYOffset ||
document.documentElement.scrollTop) -
((element && element.clientTop) || 0);
const change = scrollTo - start;
let previousTime = window.performance.now();
let currentTime = 0;
return new Promise((resolve, _reject) => {
const animateScroll = () => {
const time = window.performance.now();
const increment = time - previousTime;
previousTime = time;
currentTime += increment;
(element || document.scrollingElement || window).scrollTo(
0,
easeInOutCubic(currentTime, start, change, duration)
);
if (currentTime < duration) {
window.requestAnimationFrame(animateScroll);
}
resolve(true);
};
animateScroll();
});
}
const SPEED_MODIFIER = 0.9;
const BASE_TIME = 500;
export const calcNavScrollParams = (
linkHeight: number,
navElement: HTMLElement
) => {
const navRect = navElement.getBoundingClientRect();
let newScrollPos: number;
let scrollWindow: HTMLElement | null;
if (isMobileScreen()) {
// phone
scrollWindow = null;
newScrollPos = linkHeight - window.screen.height / 2;
} else {
// tablet
scrollWindow = navElement;
newScrollPos =
linkHeight -
navRect.top -
(navElement.offsetHeight - navElement.offsetTop) / 2;
}
const scrollTime = newScrollPos * SPEED_MODIFIER + BASE_TIME;
return {
newScrollPos,
scrollWindow,
scrollTime,
};
};