UNPKG

8.55 kBJavaScriptView Raw
1/*!
2 * ScrollToPlugin 3.10.3
3 * https://greensock.com
4 *
5 * @license Copyright 2008-2022, GreenSock. All rights reserved.
6 * Subject to the terms at https://greensock.com/standard-license or for
7 * Club GreenSock members, the agreement issued with that membership.
8 * @author: Jack Doyle, jack@greensock.com
9*/
10
11/* eslint-disable */
12var gsap,
13 _coreInitted,
14 _window,
15 _docEl,
16 _body,
17 _toArray,
18 _config,
19 _windowExists = function _windowExists() {
20 return typeof window !== "undefined";
21},
22 _getGSAP = function _getGSAP() {
23 return gsap || _windowExists() && (gsap = window.gsap) && gsap.registerPlugin && gsap;
24},
25 _isString = function _isString(value) {
26 return typeof value === "string";
27},
28 _isFunction = function _isFunction(value) {
29 return typeof value === "function";
30},
31 _max = function _max(element, axis) {
32 var dim = axis === "x" ? "Width" : "Height",
33 scroll = "scroll" + dim,
34 client = "client" + dim;
35 return element === _window || element === _docEl || element === _body ? Math.max(_docEl[scroll], _body[scroll]) - (_window["inner" + dim] || _docEl[client] || _body[client]) : element[scroll] - element["offset" + dim];
36},
37 _buildGetter = function _buildGetter(e, axis) {
38 //pass in an element and an axis ("x" or "y") and it'll return a getter function for the scroll position of that element (like scrollTop or scrollLeft, although if the element is the window, it'll use the pageXOffset/pageYOffset or the documentElement's scrollTop/scrollLeft or document.body's. Basically this streamlines things and makes a very fast getter across browsers.
39 var p = "scroll" + (axis === "x" ? "Left" : "Top");
40
41 if (e === _window) {
42 if (e.pageXOffset != null) {
43 p = "page" + axis.toUpperCase() + "Offset";
44 } else {
45 e = _docEl[p] != null ? _docEl : _body;
46 }
47 }
48
49 return function () {
50 return e[p];
51 };
52},
53 _clean = function _clean(value, index, target, targets) {
54 _isFunction(value) && (value = value(index, target, targets));
55
56 if (typeof value !== "object") {
57 return _isString(value) && value !== "max" && value.charAt(1) !== "=" ? {
58 x: value,
59 y: value
60 } : {
61 y: value
62 }; //if we don't receive an object as the parameter, assume the user intends "y".
63 } else if (value.nodeType) {
64 return {
65 y: value,
66 x: value
67 };
68 } else {
69 var result = {},
70 p;
71
72 for (p in value) {
73 result[p] = p !== "onAutoKill" && _isFunction(value[p]) ? value[p](index, target, targets) : value[p];
74 }
75
76 return result;
77 }
78},
79 _getOffset = function _getOffset(element, container) {
80 element = _toArray(element)[0];
81
82 if (!element || !element.getBoundingClientRect) {
83 return console.warn("scrollTo target doesn't exist. Using 0") || {
84 x: 0,
85 y: 0
86 };
87 }
88
89 var rect = element.getBoundingClientRect(),
90 isRoot = !container || container === _window || container === _body,
91 cRect = isRoot ? {
92 top: _docEl.clientTop - (_window.pageYOffset || _docEl.scrollTop || _body.scrollTop || 0),
93 left: _docEl.clientLeft - (_window.pageXOffset || _docEl.scrollLeft || _body.scrollLeft || 0)
94 } : container.getBoundingClientRect(),
95 offsets = {
96 x: rect.left - cRect.left,
97 y: rect.top - cRect.top
98 };
99
100 if (!isRoot && container) {
101 //only add the current scroll position if it's not the window/body.
102 offsets.x += _buildGetter(container, "x")();
103 offsets.y += _buildGetter(container, "y")();
104 }
105
106 return offsets;
107},
108 _parseVal = function _parseVal(value, target, axis, currentVal, offset) {
109 return !isNaN(value) && typeof value !== "object" ? parseFloat(value) - offset : _isString(value) && value.charAt(1) === "=" ? parseFloat(value.substr(2)) * (value.charAt(0) === "-" ? -1 : 1) + currentVal - offset : value === "max" ? _max(target, axis) - offset : Math.min(_max(target, axis), _getOffset(value, target)[axis] - offset);
110},
111 _initCore = function _initCore() {
112 gsap = _getGSAP();
113
114 if (_windowExists() && gsap && document.body) {
115 _window = window;
116 _body = document.body;
117 _docEl = document.documentElement;
118 _toArray = gsap.utils.toArray;
119 gsap.config({
120 autoKillThreshold: 7
121 });
122 _config = gsap.config();
123 _coreInitted = 1;
124 }
125};
126
127export var ScrollToPlugin = {
128 version: "3.10.3",
129 name: "scrollTo",
130 rawVars: 1,
131 register: function register(core) {
132 gsap = core;
133
134 _initCore();
135 },
136 init: function init(target, value, tween, index, targets) {
137 _coreInitted || _initCore();
138 var data = this,
139 snapType = gsap.getProperty(target, "scrollSnapType");
140 data.isWin = target === _window;
141 data.target = target;
142 data.tween = tween;
143 value = _clean(value, index, target, targets);
144 data.vars = value;
145 data.autoKill = !!value.autoKill;
146 data.getX = _buildGetter(target, "x");
147 data.getY = _buildGetter(target, "y");
148 data.x = data.xPrev = data.getX();
149 data.y = data.yPrev = data.getY();
150
151 if (snapType && snapType !== "none") {
152 // disable scroll snapping to avoid strange behavior
153 data.snap = 1;
154 data.snapInline = target.style.scrollSnapType;
155 target.style.scrollSnapType = "none";
156 }
157
158 if (value.x != null) {
159 data.add(data, "x", data.x, _parseVal(value.x, target, "x", data.x, value.offsetX || 0), index, targets);
160
161 data._props.push("scrollTo_x");
162 } else {
163 data.skipX = 1;
164 }
165
166 if (value.y != null) {
167 data.add(data, "y", data.y, _parseVal(value.y, target, "y", data.y, value.offsetY || 0), index, targets);
168
169 data._props.push("scrollTo_y");
170 } else {
171 data.skipY = 1;
172 }
173 },
174 render: function render(ratio, data) {
175 var pt = data._pt,
176 target = data.target,
177 tween = data.tween,
178 autoKill = data.autoKill,
179 xPrev = data.xPrev,
180 yPrev = data.yPrev,
181 isWin = data.isWin,
182 snap = data.snap,
183 snapInline = data.snapInline,
184 x,
185 y,
186 yDif,
187 xDif,
188 threshold;
189
190 while (pt) {
191 pt.r(ratio, pt.d);
192 pt = pt._next;
193 }
194
195 x = isWin || !data.skipX ? data.getX() : xPrev;
196 y = isWin || !data.skipY ? data.getY() : yPrev;
197 yDif = y - yPrev;
198 xDif = x - xPrev;
199 threshold = _config.autoKillThreshold;
200
201 if (data.x < 0) {
202 //can't scroll to a position less than 0! Might happen if someone uses a Back.easeOut or Elastic.easeOut when scrolling back to the top of the page (for example)
203 data.x = 0;
204 }
205
206 if (data.y < 0) {
207 data.y = 0;
208 }
209
210 if (autoKill) {
211 //note: iOS has a bug that throws off the scroll by several pixels, so we need to check if it's within 7 pixels of the previous one that we set instead of just looking for an exact match.
212 if (!data.skipX && (xDif > threshold || xDif < -threshold) && x < _max(target, "x")) {
213 data.skipX = 1; //if the user scrolls separately, we should stop tweening!
214 }
215
216 if (!data.skipY && (yDif > threshold || yDif < -threshold) && y < _max(target, "y")) {
217 data.skipY = 1; //if the user scrolls separately, we should stop tweening!
218 }
219
220 if (data.skipX && data.skipY) {
221 tween.kill();
222 data.vars.onAutoKill && data.vars.onAutoKill.apply(tween, data.vars.onAutoKillParams || []);
223 }
224 }
225
226 if (isWin) {
227 _window.scrollTo(!data.skipX ? data.x : x, !data.skipY ? data.y : y);
228 } else {
229 data.skipY || (target.scrollTop = data.y);
230 data.skipX || (target.scrollLeft = data.x);
231 }
232
233 if (snap && (ratio === 1 || ratio === 0)) {
234 y = target.scrollTop;
235 x = target.scrollLeft;
236 snapInline ? target.style.scrollSnapType = snapInline : target.style.removeProperty("scroll-snap-type");
237 target.scrollTop = y + 1; // bug in Safari causes the element to totally reset its scroll position when scroll-snap-type changes, so we need to set it to a slightly different value and then back again to work around this bug.
238
239 target.scrollLeft = x + 1;
240 target.scrollTop = y;
241 target.scrollLeft = x;
242 }
243
244 data.xPrev = data.x;
245 data.yPrev = data.y;
246 },
247 kill: function kill(property) {
248 var both = property === "scrollTo";
249
250 if (both || property === "scrollTo_x") {
251 this.skipX = 1;
252 }
253
254 if (both || property === "scrollTo_y") {
255 this.skipY = 1;
256 }
257 }
258};
259ScrollToPlugin.max = _max;
260ScrollToPlugin.getOffset = _getOffset;
261ScrollToPlugin.buildGetter = _buildGetter;
262_getGSAP() && gsap.registerPlugin(ScrollToPlugin);
263export { ScrollToPlugin as default };
\No newline at end of file