-
Notifications
You must be signed in to change notification settings - Fork 47
/
Copy pathscroll.js
118 lines (114 loc) · 3.58 KB
/
scroll.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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// eslint-disable-next-line
import { getWindow } from 'ssr-window';
function scrollTo(...args) {
const window = getWindow();
let [left, top, duration, easing, callback] = args;
if (args.length === 4 && typeof easing === 'function') {
callback = easing;
[left, top, duration, callback, easing] = args;
}
if (typeof easing === 'undefined') easing = 'swing';
return this.each(function animate() {
const el = this;
let currentTop;
let currentLeft;
let maxTop;
let maxLeft;
let newTop;
let newLeft;
let scrollTop; // eslint-disable-line
let scrollLeft; // eslint-disable-line
let animateTop = top > 0 || top === 0;
let animateLeft = left > 0 || left === 0;
if (typeof easing === 'undefined') {
easing = 'swing';
}
if (animateTop) {
currentTop = el.scrollTop;
if (!duration) {
el.scrollTop = top;
}
}
if (animateLeft) {
currentLeft = el.scrollLeft;
if (!duration) {
el.scrollLeft = left;
}
}
if (!duration) return;
if (animateTop) {
maxTop = el.scrollHeight - el.offsetHeight;
newTop = Math.max(Math.min(top, maxTop), 0);
}
if (animateLeft) {
maxLeft = el.scrollWidth - el.offsetWidth;
newLeft = Math.max(Math.min(left, maxLeft), 0);
}
let startTime = null;
if (animateTop && newTop === currentTop) animateTop = false;
if (animateLeft && newLeft === currentLeft) animateLeft = false;
function render(time = new Date().getTime()) {
if (startTime === null) {
startTime = time;
}
const progress = Math.max(Math.min((time - startTime) / duration, 1), 0);
const easeProgress =
easing === 'linear' ? progress : 0.5 - Math.cos(progress * Math.PI) / 2;
let done;
if (animateTop)
scrollTop = currentTop + easeProgress * (newTop - currentTop);
if (animateLeft)
scrollLeft = currentLeft + easeProgress * (newLeft - currentLeft);
if (animateTop && newTop > currentTop && scrollTop >= newTop) {
el.scrollTop = newTop;
done = true;
}
if (animateTop && newTop < currentTop && scrollTop <= newTop) {
el.scrollTop = newTop;
done = true;
}
if (animateLeft && newLeft > currentLeft && scrollLeft >= newLeft) {
el.scrollLeft = newLeft;
done = true;
}
if (animateLeft && newLeft < currentLeft && scrollLeft <= newLeft) {
el.scrollLeft = newLeft;
done = true;
}
if (done) {
if (callback) callback();
return;
}
if (animateTop) el.scrollTop = scrollTop;
if (animateLeft) el.scrollLeft = scrollLeft;
window.requestAnimationFrame(render);
}
window.requestAnimationFrame(render);
});
}
// scrollTop(top, duration, easing, callback) {
function scrollTop(...args) {
let [top, duration, easing, callback] = args;
if (args.length === 3 && typeof easing === 'function') {
[top, duration, callback, easing] = args;
}
const dom = this;
if (typeof top === 'undefined') {
if (dom.length > 0) return dom[0].scrollTop;
return null;
}
return dom.scrollTo(undefined, top, duration, easing, callback);
}
function scrollLeft(...args) {
let [left, duration, easing, callback] = args;
if (args.length === 3 && typeof easing === 'function') {
[left, duration, callback, easing] = args;
}
const dom = this;
if (typeof left === 'undefined') {
if (dom.length > 0) return dom[0].scrollLeft;
return null;
}
return dom.scrollTo(left, undefined, duration, easing, callback);
}
export { scrollTo, scrollTop, scrollLeft };