gsap
Version:
GSAP is a JavaScript library for building high-performance animations that work in **every** major browser. Animate CSS, SVG, canvas, React, Vue, WebGL, colors, strings, motion paths, generic objects...anything JavaScript can touch! The ScrollTrigger plug
1,292 lines (1,105 loc) • 42.3 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = global || self, factory(global.window = global.window || {}));
}(this, (function (exports) { 'use strict';
/*!
* ScrollTrigger 3.3.4
* https://greensock.com
*
* @license Copyright 2008-2020, GreenSock. All rights reserved.
* Subject to the terms at https://greensock.com/standard-license or for
* Club GreenSock members, the agreement issued with that membership.
* @author: Jack Doyle, jack@greensock.com
*/
var gsap,
_coreInitted,
_win,
_doc,
_docEl,
_body,
_root,
_resizeDelay,
_raf,
_request,
_toArray,
_clamp,
_time2,
_syncInterval,
_refreshing,
_pointerIsDown,
_transformProp,
_i,
_limitCallbacks,
_startup = 1,
_getTime = Date.now,
_time1 = _getTime(),
_lastScrollTime = 0,
_enabled = 1,
_passThrough = function _passThrough(v) {
return v;
},
_windowExists = function _windowExists() {
return typeof window !== "undefined";
},
_getGSAP = function _getGSAP() {
return gsap || _windowExists() && (gsap = window.gsap) && gsap.registerPlugin && gsap;
},
_isViewport = function _isViewport(e) {
return !!~_root.indexOf(e);
},
_getScrollFunc = function _getScrollFunc(element, _ref) {
var s = _ref.s;
return function (value) {
return arguments.length ? element[s] = value : element[s];
};
},
_maxScroll = function _maxScroll(element, _ref2) {
var s = _ref2.s,
d2 = _ref2.d2;
return (s = "scroll" + d2) && _isViewport(element) ? Math.max(_docEl[s], _body[s]) - (_win["inner" + d2] || _docEl["client" + d2] || _body["client" + d2]) : element[s] - element["offset" + d2];
},
_isString = function _isString(value) {
return typeof value === "string";
},
_isFunction = function _isFunction(value) {
return typeof value === "function";
},
_isNumber = function _isNumber(value) {
return typeof value === "number";
},
_isObject = function _isObject(value) {
return typeof value === "object";
},
_abs = Math.abs,
_scrollLeft = "scrollLeft",
_scrollTop = "scrollTop",
_left = "left",
_top = "top",
_right = "right",
_bottom = "bottom",
_width = "width",
_height = "height",
_Right = "Right",
_Left = "Left",
_Top = "Top",
_Bottom = "Bottom",
_padding = "padding",
_margin = "margin",
_Width = "Width",
_Height = "Height",
_px = "px",
_horizontal = {
s: _scrollLeft,
p: _left,
p2: _Left,
os: _right,
os2: _Right,
d: _width,
d2: _Width,
a: "x",
sc: function sc(value) {
return arguments.length ? _win.scrollTo(value, _vertical.sc()) : _win.pageXOffset || _doc[_scrollLeft] || _docEl[_scrollLeft] || _body[_scrollLeft] || 0;
}
},
_vertical = {
s: _scrollTop,
p: _top,
p2: _Top,
os: _bottom,
os2: _Bottom,
d: _height,
d2: _Height,
a: "y",
op: _horizontal,
sc: function sc(value) {
return arguments.length ? _win.scrollTo(_horizontal.sc(), value) : _win.pageYOffset || _doc[_scrollTop] || _docEl[_scrollTop] || _body[_scrollTop] || 0;
}
},
_getComputedStyle = function _getComputedStyle(element) {
return _win.getComputedStyle(element);
},
_makePositionable = function _makePositionable(element) {
return element.style.position = _getComputedStyle(element).position === "absolute" ? "absolute" : "relative";
},
_setDefaults = function _setDefaults(obj, defaults) {
for (var p in defaults) {
p in obj || (obj[p] = defaults[p]);
}
return obj;
},
_getBounds = function _getBounds(element, withoutTransforms) {
var tween = withoutTransforms && _getComputedStyle(element)[_transformProp] !== "matrix(1, 0, 0, 1, 0, 0)" && gsap.to(element, {
x: 0,
y: 0,
xPercent: 0,
yPercent: 0,
rotation: 0,
rotationX: 0,
rotationY: 0,
scale: 1,
skewX: 0,
skewY: 0
}).progress(1),
bounds = element.getBoundingClientRect();
tween && tween.progress(0).kill();
return bounds;
},
_getSize = function _getSize(element, _ref3) {
var d2 = _ref3.d2;
return element["offset" + d2] || element["client" + d2] || 0;
},
_getLabels = function _getLabels(animation) {
return function (value) {
var a = [],
labels = animation.labels,
duration = animation.duration(),
p;
for (p in labels) {
a.push(labels[p] / duration);
}
return gsap.utils.snap(a, value);
};
},
_multiListener = function _multiListener(func, element, types, callback) {
return types.split(",").forEach(function (type) {
return func(element, type, callback);
});
},
_addListener = function _addListener(element, type, func) {
return element.addEventListener(type, func, {
passive: true
});
},
_removeListener = function _removeListener(element, type, func) {
return element.removeEventListener(type, func);
},
_markerDefaults = {
startColor: "green",
endColor: "red",
indent: 0,
fontSize: "16px",
fontWeight: "normal"
},
_defaults = {
toggleActions: "play",
anticipatePin: 0
},
_keywords = {
top: 0,
left: 0,
center: 0.5,
bottom: 1,
right: 1
},
_offsetToPx = function _offsetToPx(value, size) {
if (_isString(value)) {
var eqIndex = value.indexOf("="),
relative = ~eqIndex ? +(value.charAt(eqIndex - 1) + 1) * parseFloat(value.substr(eqIndex + 1)) : 0;
if (relative) {
value.indexOf("%") > eqIndex && (relative *= size / 100);
value = value.substr(0, eqIndex - 1);
}
value = relative + (value in _keywords ? _keywords[value] * size : ~value.indexOf("%") ? parseFloat(value) * size / 100 : parseFloat(value) || 0);
}
return value;
},
_createMarker = function _createMarker(type, name, container, direction, _ref4, offset, matchWidthEl) {
var startColor = _ref4.startColor,
endColor = _ref4.endColor,
fontSize = _ref4.fontSize,
indent = _ref4.indent,
fontWeight = _ref4.fontWeight;
var e = _doc.createElement("div"),
isViewport = _isViewport(container),
isScroller = type.indexOf("scroller") !== -1,
parent = isViewport ? _body : container,
isStart = type.indexOf("start") !== -1,
color = isStart ? startColor : endColor,
css = "border-color:" + color + ";font-size:" + fontSize + ";color:" + color + ";font-weight:" + fontWeight + ";pointer-events:none;white-space:nowrap;font-family:sans-serif,Arial;z-index:1000;padding:4px 8px;border-width:0;border-style:solid;";
css += "position:" + (isScroller && isViewport ? "fixed;" : "absolute;");
(isScroller || !isViewport) && (css += (direction === _vertical ? _right : _bottom) + ":" + (offset + parseFloat(indent)) + "px;");
matchWidthEl && (css += "box-sizing:border-box;text-align:left;width:" + matchWidthEl.offsetWidth + "px;");
e._isStart = isStart;
e.setAttribute("class", "gsap-marker-" + type);
e.style.cssText = css;
e.innerText = name || name === 0 ? type + "-" + name : type;
parent.insertBefore(e, parent.children[0]);
e._offset = e["offset" + direction.op.d2];
_positionMarker(e, 0, direction, isViewport, isStart);
return e;
},
_positionMarker = function _positionMarker(marker, start, direction, isViewport, flipped) {
var vars = {},
side = direction[flipped ? "os2" : "p2"],
oppositeSide = direction[flipped ? "p2" : "os2"];
marker._isFlipped = flipped;
vars[direction.a + "Percent"] = flipped ? -100 : 0;
vars[direction.a] = flipped ? 1 : 0;
vars["border" + side + _Width] = 1;
vars["border" + oppositeSide + _Width] = 0;
vars[direction.p] = start;
gsap.set(marker, vars);
},
_triggers = [],
_ids = {},
_sync = function _sync() {
return _request || (_request = _raf(_updateAll));
},
_onScroll = function _onScroll() {
if (!_request) {
_request = _raf(_updateAll);
_lastScrollTime || _dispatch("scrollStart");
_lastScrollTime = _getTime();
}
},
_onResize = function _onResize() {
return !_refreshing && _getTime() - _lastScrollTime > 200 && _resizeDelay.restart(true);
},
_listeners = {},
_emptyArray = [],
_dispatch = function _dispatch(type) {
return _listeners[type] && _listeners[type].map(function (f) {
return f();
}) || _emptyArray;
},
_refreshAll = function _refreshAll(force) {
var refreshInits = _dispatch("refreshInit"),
l = _triggers.length;
_i = l;
while (_i--) {
_triggers[_i].scroll.rec = _triggers[_i].scroll();
}
for (_i = 0; _i < l; _i++) {
_triggers[_i] && _triggers[_i].refresh(force !== true);
}
refreshInits.forEach(function (result) {
return result && result.render && result.render(-1);
});
_i = _triggers.length;
while (_i--) {
_triggers[_i].scroll.rec = 0;
}
_dispatch("refresh");
},
_updateAll = function _updateAll() {
var l = _triggers.length,
time = _getTime(),
recordVelocity = time - _time1 >= 50;
if (recordVelocity) {
if (_lastScrollTime && !_pointerIsDown && time - _lastScrollTime > 200) {
_lastScrollTime = 0;
_dispatch("scrollEnd");
}
_time2 = _time1;
_time1 = time;
}
for (_i = 0; _i < l; _i++) {
_triggers[_i] && _triggers[_i].update(0, recordVelocity);
}
_request = 0;
},
_propNamesToCopy = [_left, _top, _bottom, _right, _margin + _Bottom, _margin + _Right, _margin + _Top, _margin + _Left, "display", "flexShrink"],
_stateProps = _propNamesToCopy.concat([_width, _height, "boxSizing", "max" + _Width, "max" + _Height, "position", _margin, _padding, _padding + _Top, _padding + _Right, _padding + _Bottom, _padding + _Left]),
_swapPinOut = function _swapPinOut(pin, spacer, state) {
_setState(state);
if (pin.parentNode === spacer) {
var parent = spacer.parentNode;
if (parent) {
parent.insertBefore(pin, spacer);
parent.removeChild(spacer);
}
}
},
_swapPinIn = function _swapPinIn(pin, spacer, cs) {
if (pin.parentNode !== spacer) {
var i = _propNamesToCopy.length,
spacerStyle = spacer.style,
pinStyle = pin.style,
p;
while (i--) {
p = _propNamesToCopy[i];
spacerStyle[p] = cs[p];
}
spacerStyle.position = cs.position === "absolute" ? "absolute" : "relative";
pinStyle[_bottom] = pinStyle[_right] = "auto";
spacerStyle.overflow = "visible";
spacerStyle.boxSizing = "border-box";
spacerStyle[_width] = _getSize(pin, _horizontal) + _px;
spacerStyle[_height] = _getSize(pin, _vertical) + _px;
spacerStyle[_padding] = pinStyle[_margin] = pinStyle[_top] = pinStyle[_left] = "0";
pinStyle[_width] = cs[_width];
pinStyle[_height] = cs[_height];
pinStyle[_padding] = cs[_padding];
pin.parentNode.insertBefore(spacer, pin);
spacer.appendChild(pin);
}
},
_capsExp = /([A-Z])/g,
_setState = function _setState(state) {
var style = state.t.style,
l = state.length,
i = 0,
p,
value;
for (; i < l; i += 2) {
value = state[i + 1];
p = state[i];
if (value) {
style[p] = value;
} else if (style[p]) {
style.removeProperty(p.replace(_capsExp, "-$1").toLowerCase());
}
}
},
_getState = function _getState(element) {
var l = _stateProps.length,
style = element.style,
state = [],
i = 0;
for (; i < l; i++) {
state.push(_stateProps[i], style[_stateProps[i]]);
}
state.t = element;
return state;
},
_copyState = function _copyState(state, override, omitOffsets) {
var result = [],
l = state.length,
i = omitOffsets ? 8 : 0,
p;
for (; i < l; i += 2) {
p = state[i];
result.push(p, p in override ? override[p] : state[i + 1]);
}
result.t = state.t;
return result;
},
_winOffsets = {
left: 0,
top: 0
},
_parsePosition = function _parsePosition(value, trigger, scrollerSize, direction, scroll, marker, markerScroller, self, scrollerBounds, borderWidth, isViewport, scrollerMax) {
_isFunction(value) && (value = value(self));
if (_isString(value) && value.substr(0, 3) === "max") {
value = scrollerMax + (value.charAt(4) === "=" ? _offsetToPx("0" + value.substr(3), scrollerSize) : 0);
}
if (!_isNumber(value)) {
_isFunction(trigger) && (trigger = trigger(self));
var element = _toArray(trigger)[0] || _body,
bounds = _getBounds(element) || {},
offsets = value.split(" "),
localOffset,
globalOffset,
display;
if ((!bounds || !bounds.left && !bounds.top) && _getComputedStyle(element).display === "none") {
display = element.style.display;
element.style.display = "block";
bounds = _getBounds(element);
display ? element.style.display = display : element.style.removeProperty("display");
}
localOffset = _offsetToPx(offsets[0], bounds[direction.d]);
globalOffset = _offsetToPx(offsets[1] || "0", scrollerSize);
value = bounds[direction.p] - scrollerBounds[direction.p] - borderWidth + localOffset + scroll - globalOffset;
markerScroller && _positionMarker(markerScroller, globalOffset, direction, isViewport, scrollerSize - globalOffset < 20 || markerScroller._isStart && globalOffset > 20);
scrollerSize -= scrollerSize - globalOffset;
} else if (markerScroller) {
_positionMarker(markerScroller, scrollerSize, direction, isViewport, true);
}
if (marker) {
var position = value + scrollerSize,
isStart = marker._isStart;
scrollerMax = "scroll" + direction.d2;
_positionMarker(marker, position, direction, isViewport, isStart && position > 20 || !isStart && (isViewport ? Math.max(_body[scrollerMax], _docEl[scrollerMax]) : marker.parentNode[scrollerMax]) <= position + 1);
if (isViewport) {
scrollerBounds = _getBounds(markerScroller);
isViewport && (marker.style[direction.op.p] = scrollerBounds[direction.op.p] - direction.op.m - marker._offset + _px);
}
}
return Math.round(value);
},
_prefixExp = /(?:webkit|moz|length)/i,
_reparent = function _reparent(element, parent) {
if (element.parentNode !== parent) {
var style = element.style,
p,
cs;
if (parent === _body) {
element._stOrig = style.cssText;
cs = _getComputedStyle(element);
for (p in cs) {
if (!+p && !_prefixExp.test(p) && cs[p] && typeof style[p] === "string" && p !== "0") {
style[p] = cs[p];
}
}
} else {
style.cssText = element._stOrig;
}
parent.appendChild(element);
}
},
_getTweenCreator = function _getTweenCreator(scroller, direction) {
var getScroll = _isViewport(scroller) ? direction.sc : _getScrollFunc(scroller, direction),
prop = "_scroll" + direction.p2,
lastScroll,
getTween = function getTween(scrollTo, vars, initialValue, change1, change2) {
var tween = getTween.tween,
onComplete = vars.onComplete,
modifiers = {};
tween && tween.kill();
lastScroll = getScroll();
vars[prop] = scrollTo;
vars.modifiers = modifiers;
modifiers[prop] = function (value) {
if (getScroll() !== lastScroll) {
tween.kill();
getTween.tween = 0;
value = getScroll();
} else if (change1) {
value = initialValue + change1 * tween.ratio + change2 * tween.ratio * tween.ratio;
}
return lastScroll = Math.round(value);
};
vars.onComplete = function () {
getTween.tween = 0;
onComplete && onComplete.call(tween);
};
tween = getTween.tween = gsap.to(scroller, vars);
return tween;
};
scroller[prop] = getScroll;
return getTween;
};
_horizontal.op = _vertical;
var ScrollTrigger = function () {
function ScrollTrigger(vars, animation) {
_coreInitted || ScrollTrigger.register(gsap) || console.warn("Please gsap.registerPlugin(ScrollTrigger)");
this.init(vars, animation);
}
var _proto = ScrollTrigger.prototype;
_proto.init = function init(vars, animation) {
this.progress = 0;
this.vars && this.kill(1);
if (!_enabled) {
this.update = this.refresh = this.kill = _passThrough;
return;
}
vars = _setDefaults(_isString(vars) || _isNumber(vars) || vars.nodeType ? {
trigger: vars
} : vars, _defaults);
var direction = vars.horizontal ? _horizontal : _vertical,
_vars = vars,
onUpdate = _vars.onUpdate,
toggleClass = _vars.toggleClass,
id = _vars.id,
onToggle = _vars.onToggle,
onRefresh = _vars.onRefresh,
scrub = _vars.scrub,
trigger = _vars.trigger,
pin = _vars.pin,
pinSpacing = _vars.pinSpacing,
invalidateOnRefresh = _vars.invalidateOnRefresh,
anticipatePin = _vars.anticipatePin,
onScrubComplete = _vars.onScrubComplete,
onSnapComplete = _vars.onSnapComplete,
once = _vars.once,
snap = _vars.snap,
pinReparent = _vars.pinReparent,
isToggle = !scrub && scrub !== 0,
scroller = _toArray(vars.scroller || _win)[0],
scrollerCache = gsap.core.getCache(scroller),
isViewport = _isViewport(scroller),
callbacks = [vars.onEnter, vars.onLeave, vars.onEnterBack, vars.onLeaveBack],
toggleActions = isToggle && (once ? "play" : vars.toggleActions).split(" "),
markers = "markers" in vars ? vars.markers : _defaults.markers,
borderWidth = isViewport ? 0 : parseFloat(_getComputedStyle(scroller)["border" + direction.p2 + _Width]) || 0,
self = this,
softRefresh = function softRefresh() {
return ScrollTrigger.removeEventListener("scrollEnd", softRefresh) || self.refresh();
},
onRefreshInit = vars.onRefreshInit && function () {
return vars.onRefreshInit(self);
},
tweenTo,
pinCache,
snapFunc,
isReverted,
scroll1,
scroll2,
start,
end,
markerStart,
markerEnd,
markerStartTrigger,
markerEndTrigger,
markerVars,
change,
pinOriginalState,
pinActiveState,
pinState,
spacer,
offset,
pinGetter,
pinSetter,
pinStart,
pinChange,
spacingStart,
spacingActive,
markerStartSetter,
markerEndSetter,
cs,
snap1,
snap2,
scrubScrollTime,
scrubTween,
scrubSmooth,
snapDurClamp,
snapDelayedCall,
enabled;
anticipatePin *= 45;
_triggers.push(self);
self.scroller = scroller;
self.scroll = isViewport ? direction.sc : _getScrollFunc(scroller, direction);
scroll1 = self.scroll();
self.vars = vars;
animation = animation || vars.animation;
scrollerCache.tweenScroll = scrollerCache.tweenScroll || {
top: _getTweenCreator(scroller, _vertical),
left: _getTweenCreator(scroller, _horizontal)
};
self.tweenTo = tweenTo = scrollerCache.tweenScroll[direction.p];
if (animation) {
animation.vars.lazy = false;
animation._initted || animation.vars.immediateRender !== false && animation.render(-0.01, true, true);
self.animation = animation.pause();
animation.scrollTrigger = self;
scrubSmooth = _isNumber(scrub) && scrub;
scrubSmooth && (scrubTween = gsap.to(animation, {
ease: "power3",
duration: scrubSmooth,
onComplete: function onComplete() {
return onScrubComplete && onScrubComplete(self);
}
}));
snap1 = 0;
id || (id = animation.vars.id);
}
if (snap) {
_isObject(snap) || (snap = {
snapTo: snap
});
snapFunc = _isFunction(snap.snapTo) ? snap.snapTo : snap.snapTo === "labels" ? _getLabels(animation) : gsap.utils.snap(snap.snapTo);
snapDurClamp = snap.duration || {
min: 0.1,
max: 2
};
snapDurClamp = _isObject(snapDurClamp) ? _clamp(snapDurClamp.min, snapDurClamp.max) : _clamp(snapDurClamp, snapDurClamp);
snapDelayedCall = gsap.delayedCall(snap.delay || scrubSmooth / 2 || 0.1, function () {
if (!_lastScrollTime || _lastScrollTime === scrubScrollTime && !_pointerIsDown) {
var totalProgress = animation && !isToggle ? animation.totalProgress() : self.progress,
velocity = (totalProgress - snap2) / (_getTime() - _time2) * 1000 || 0,
change1 = _abs(velocity / 2) * velocity / 0.185,
naturalEnd = totalProgress + change1,
endValue = _clamp(0, 1, snapFunc(naturalEnd, self)),
change2 = endValue - totalProgress - change1,
scroll = self.scroll(),
endScroll = Math.round(start + endValue * change),
tween = tweenTo.tween;
if (scroll <= end && scroll >= start) {
if (tween && !tween._initted) {
if (tween.data <= Math.abs(endScroll - scroll)) {
return;
}
tween.kill();
}
tweenTo(endScroll, {
duration: snapDurClamp(_abs(Math.max(_abs(naturalEnd - totalProgress), _abs(endValue - totalProgress)) * 0.185 / velocity / 0.05 || 0)),
ease: snap.ease || "power3",
data: Math.abs(endScroll - scroll),
onComplete: function onComplete() {
snap1 = snap2 = animation && !isToggle ? animation.totalProgress() : self.progress;
onSnapComplete && onSnapComplete(self);
}
}, start + totalProgress * change, change1 * change, change2 * change);
}
} else {
snapDelayedCall.restart(true);
}
}).pause();
}
id && (_ids[id] = self);
trigger = self.trigger = _toArray(trigger || pin)[0];
pin = pin === true ? trigger : _toArray(pin)[0];
_isString(toggleClass) && (toggleClass = {
targets: trigger,
className: toggleClass
});
if (pin) {
pinSpacing === false || pinSpacing === _margin || (pinSpacing = _getComputedStyle(pin.parentNode).display === "flex" ? false : _padding);
self.pin = pin;
vars.force3D !== false && gsap.set(pin, {
force3D: true
});
pinCache = gsap.core.getCache(pin);
if (!pinCache.spacer) {
pinCache.spacer = spacer = _doc.createElement("div");
spacer.setAttribute("class", "pin-spacer" + (id ? " pin-spacer-" + id : ""));
pinCache.pinState = pinOriginalState = _getState(pin);
} else {
pinOriginalState = pinCache.pinState;
}
self.spacer = spacer = pinCache.spacer;
cs = _getComputedStyle(pin);
spacingStart = cs[pinSpacing + direction.os2];
pinGetter = gsap.getProperty(pin);
pinSetter = gsap.quickSetter(pin, direction.a, _px);
_swapPinIn(pin, spacer, cs);
pinState = _getState(pin);
}
if (markers) {
markerVars = _isObject(markers) ? _setDefaults(markers, _markerDefaults) : _markerDefaults;
markerStartTrigger = _createMarker("scroller-start", id, scroller, direction, markerVars, 0);
markerEndTrigger = _createMarker("scroller-end", id, scroller, direction, markerVars, 0, markerStartTrigger);
offset = markerStartTrigger["offset" + direction.op.d2];
markerStart = _createMarker("start", id, scroller, direction, markerVars, offset);
markerEnd = _createMarker("end", id, scroller, direction, markerVars, offset);
if (!isViewport) {
_makePositionable(scroller);
gsap.set([markerStartTrigger, markerEndTrigger], {
force3D: true
});
markerStartSetter = gsap.quickSetter(markerStartTrigger, direction.a, _px);
markerEndSetter = gsap.quickSetter(markerEndTrigger, direction.a, _px);
}
}
self.revert = function (revert) {
var r = revert !== false;
if (r !== isReverted) {
self.update(r);
pin && r && _swapPinOut(pin, spacer, pinOriginalState);
isReverted = r;
}
};
self.refresh = function (soft) {
if (_refreshing || !enabled) {
return;
}
if (pin && soft && _lastScrollTime) {
_addListener(ScrollTrigger, "scrollEnd", softRefresh);
return;
}
var prevScroll = Math.max(self.scroll(), self.scroll.rec || 0),
prevProgress = self.progress,
prevAnimProgress = animation && animation.progress();
_refreshing = 1;
scrubTween && scrubTween.kill();
invalidateOnRefresh && animation && animation.progress(0).invalidate().progress(self.progress);
isReverted || self.revert();
var size = (isViewport ? _win["inner" + direction.d2] : scroller["client" + direction.d2]) || 0,
scrollerBounds = isViewport ? _winOffsets : _getBounds(scroller),
max = _maxScroll(scroller, direction),
offset = 0,
otherPinOffset = 0,
parsedEnd = vars.end,
parsedEndTrigger = vars.endTrigger || trigger,
parsedStart = vars.start || (pin || !trigger ? "0 0" : "0 100%"),
pinIndex = pin && Math.max(0, _triggers.indexOf(self)) || 0,
cs,
bounds,
scroll,
isVertical,
override,
i,
curTrigger;
if (pinIndex) {
i = pinIndex;
while (i--) {
_triggers[i].pin === pin && _triggers[i].revert();
}
}
start = _parsePosition(parsedStart, trigger, size, direction, self.scroll(), markerStart, markerStartTrigger, self, scrollerBounds, borderWidth, isViewport, max) || (pin ? -0.001 : 0);
_isFunction(parsedEnd) && (parsedEnd = parsedEnd(self));
if (_isString(parsedEnd) && !parsedEnd.indexOf("+=")) {
if (~parsedEnd.indexOf(" ")) {
parsedEnd = (_isString(parsedStart) ? parsedStart.split(" ")[0] : "") + parsedEnd;
} else {
offset = _offsetToPx(parsedEnd.substr(2), size);
parsedEnd = _isString(parsedStart) ? parsedStart : start + offset;
parsedEndTrigger = trigger;
}
}
end = Math.max(start, _parsePosition(parsedEnd || (parsedEndTrigger ? "100% 0" : max), parsedEndTrigger, size, direction, self.scroll() + offset, markerEnd, markerEndTrigger, self, scrollerBounds, borderWidth, isViewport, max)) || -0.001;
change = end - start || (start -= 0.01) && 0.001;
if (pin) {
i = pinIndex;
while (i--) {
curTrigger = _triggers[i];
if (curTrigger.pin === pin && curTrigger.start - curTrigger._pinPush < start) {
otherPinOffset += curTrigger.end - curTrigger.start;
}
}
start += otherPinOffset;
end += otherPinOffset;
self._pinPush = otherPinOffset;
if (markerStart && otherPinOffset) {
cs = {};
cs[direction.a] = "+=" + otherPinOffset;
gsap.set([markerStart, markerEnd], cs);
}
cs = _getComputedStyle(pin);
isVertical = direction === _vertical;
scroll = self.scroll();
pinStart = parseFloat(pinGetter(direction.a)) + otherPinOffset;
_swapPinIn(pin, spacer, cs);
pinState = _getState(pin);
bounds = _getBounds(pin, true);
if (pinSpacing) {
spacer.style[pinSpacing + direction.os2] = change + otherPinOffset + _px;
spacingActive = pinSpacing === _padding ? _getSize(pin, direction) + change + otherPinOffset : 0;
spacingActive && (spacer.style[direction.d] = spacingActive + _px);
isViewport && self.scroll(prevScroll);
}
if (isViewport) {
override = {
top: bounds.top + (isVertical ? scroll - start : 0) + _px,
left: bounds.left + (isVertical ? 0 : scroll - start) + _px,
boxSizing: "border-box",
position: "fixed"
};
override[_width] = override["max" + _Width] = Math.ceil(bounds.width) + _px;
override[_height] = override["max" + _Height] = Math.ceil(bounds.height) + _px;
override[_margin] = override[_margin + _Top] = override[_margin + _Right] = override[_margin + _Bottom] = override[_margin + _Left] = "0";
override[_padding] = cs[_padding];
override[_padding + _Top] = cs[_padding + _Top];
override[_padding + _Right] = cs[_padding + _Right];
override[_padding + _Bottom] = cs[_padding + _Bottom];
override[_padding + _Left] = cs[_padding + _Left];
pinActiveState = _copyState(pinOriginalState, override, pinReparent);
}
if (animation) {
animation.progress(1, true);
pinChange = pinGetter(direction.a) - pinStart + change + otherPinOffset;
change !== pinChange && pinActiveState.splice(pinActiveState.length - 2, 2);
animation.progress(0, true);
} else {
pinChange = change;
}
if (pinIndex) {
for (i = 0; i < pinIndex; i++) {
_triggers[i].pin === pin && _triggers[i].revert(false);
}
}
} else if (trigger && self.scroll()) {
bounds = trigger.parentNode;
while (bounds && bounds !== _body) {
if (bounds._pinOffset) {
start -= bounds._pinOffset;
end -= bounds._pinOffset;
}
bounds = bounds.parentNode;
}
}
self.start = start;
self.end = end;
self.scroll() < prevScroll && self.scroll(prevScroll);
self.revert(false);
_refreshing = 0;
prevAnimProgress && isToggle && animation.progress(prevAnimProgress, true);
if (prevProgress !== self.progress) {
scrubTween && animation.totalProgress(prevProgress, true);
self.progress = prevProgress;
self.update();
}
pin && pinSpacing && (spacer._pinOffset = Math.round(self.progress * pinChange));
onRefresh && onRefresh(self);
};
self.getVelocity = function () {
return (self.scroll() - scroll2) / (_getTime() - _time2) * 1000 || 0;
};
self.update = function (reset, recordVelocity) {
var scroll = self.scroll(),
p = reset ? 0 : (scroll - start) / change,
clipped = p < 0 ? 0 : p > 1 ? 1 : p || 0,
prevProgress = self.progress,
isActive,
wasActive,
toggleState,
action,
stateChanged,
toggled;
if (recordVelocity) {
scroll2 = scroll1;
scroll1 = scroll;
if (snap) {
snap2 = snap1;
snap1 = animation && !isToggle ? animation.totalProgress() : clipped;
}
}
anticipatePin && !clipped && pin && !_refreshing && start < scroll + (scroll - scroll2) / (_getTime() - _time2) * anticipatePin && (clipped = 0.0001);
if (clipped !== prevProgress && enabled) {
isActive = self.isActive = !!clipped && clipped < 1;
wasActive = !!prevProgress && prevProgress < 1;
toggled = isActive !== wasActive;
stateChanged = toggled || !!clipped !== !!prevProgress;
self.direction = clipped > prevProgress ? 1 : -1;
self.progress = clipped;
if (!isToggle) {
if (scrubTween && !_refreshing && !_startup) {
scrubTween.vars.totalProgress = clipped;
scrubTween.invalidate().restart();
} else if (animation) {
animation.totalProgress(clipped, !!_refreshing);
}
}
if (pin) {
reset && pinSpacing && (spacer.style[pinSpacing + direction.os2] = spacingStart);
if (!isViewport) {
pinSetter(pinStart + pinChange * clipped);
} else if (stateChanged) {
action = !reset && end + 1 > scroll && scroll + 1 >= _maxScroll(scroller, direction);
if (pinReparent) {
if (!_refreshing && (isActive || action)) {
var bounds = _getBounds(pin, true),
_offset = scroll - start;
pin.style.top = bounds.top + (direction === _vertical ? _offset : 0) + _px;
pin.style.left = bounds.left + (direction === _vertical ? 0 : _offset) + _px;
}
_reparent(pin, !_refreshing && (isActive || action) ? _body : spacer);
}
_setState(isActive || action ? pinActiveState : pinState);
pinChange !== change && clipped < 1 && isActive || pinSetter(pinStart + (clipped === 1 && !action ? pinChange : 0));
}
}
if (snap && !tweenTo.tween && !_refreshing && !_startup) {
scrubScrollTime = _lastScrollTime;
snapDelayedCall.restart(true);
}
toggleClass && toggled && (!once || isActive) && _toArray(toggleClass.targets).forEach(function (el) {
return el.classList[isActive ? "add" : "remove"](toggleClass.className);
});
onUpdate && !isToggle && !reset && onUpdate(self);
if (stateChanged && !_refreshing) {
toggleState = clipped && !prevProgress ? 0 : clipped === 1 ? 1 : prevProgress === 1 ? 2 : 3;
if (isToggle) {
action = !toggled && toggleActions[toggleState + 1] !== "none" && toggleActions[toggleState + 1] || toggleActions[toggleState];
if (animation && (action === "complete" || action === "reset" || action in animation)) {
if (action === "complete") {
animation.pause().totalProgress(1);
} else if (action === "reset") {
animation.restart(true).pause();
} else {
animation[action]();
}
}
onUpdate && onUpdate(self);
}
if (toggled || !_limitCallbacks) {
onToggle && toggled && onToggle(self);
callbacks[toggleState] && callbacks[toggleState](self);
once && (clipped === 1 ? self.kill() : callbacks[toggleState] = 0);
if (!toggled) {
toggleState = clipped === 1 ? 1 : 3;
callbacks[toggleState] && callbacks[toggleState](self);
}
}
} else if (isToggle && onUpdate && !_refreshing) {
onUpdate(self);
}
}
if (markerEndSetter) {
markerStartSetter(scroll + (markerStartTrigger._isFlipped ? 1 : 0));
markerEndSetter(scroll);
}
};
self.enable = function () {
if (!enabled) {
enabled = true;
_addListener(scroller, "resize", _onResize);
_addListener(scroller, "scroll", _onScroll);
onRefreshInit && _addListener(ScrollTrigger, "refreshInit", onRefreshInit);
!animation || !animation.add ? self.refresh() : gsap.delayedCall(0.01, self.refresh) && (change = 0.01) && (start = end = 0);
}
};
self.disable = function (reset) {
if (enabled) {
enabled = self.isActive = false;
scrubTween && scrubTween.pause();
reset !== enabled && self.update(1);
pin && _swapPinOut(pin, spacer, pinOriginalState);
onRefreshInit && _removeListener(ScrollTrigger, "refreshInit", onRefreshInit);
if (snapDelayedCall) {
snapDelayedCall.pause();
tweenTo.tween && tweenTo.tween.kill();
}
if (!isViewport) {
var i = _triggers.length;
while (i--) {
if (_triggers[i].scroller === scroller && _triggers[i] !== self) {
return;
}
}
_removeListener(scroller, "resize", _onResize);
_removeListener(scroller, "scroll", _onScroll);
}
}
};
self.kill = function (reset) {
self.disable(reset);
id && delete _ids[id];
var i = _triggers.indexOf(self);
_triggers.splice(i, 1);
i === _i && _i--;
animation && (animation.scrollTrigger = null);
};
self.enable();
};
ScrollTrigger.register = function register(core) {
gsap = core || _getGSAP();
if (_windowExists() && window.document) {
_win = window;
_doc = document;
_docEl = _doc.documentElement;
_body = _doc.body;
}
if (gsap) {
_toArray = gsap.utils.toArray;
_clamp = gsap.utils.clamp;
gsap.core.globals("ScrollTrigger", ScrollTrigger);
if (_body) {
_raf = _win.requestAnimationFrame || function (f) {
return setTimeout(f, 16);
};
_addListener(_win, "mousewheel", _onScroll);
_root = [_win, _doc, _docEl, _body];
_addListener(_doc, "scroll", _onScroll);
var bodyStyle = _body.style,
border = bodyStyle.borderTop,
bounds;
bodyStyle.borderTop = "1px solid #000";
bounds = _getBounds(_body);
_vertical.m = Math.round(bounds.top + _vertical.sc()) || 0;
_horizontal.m = Math.round(bounds.left + _horizontal.sc()) || 0;
border ? bodyStyle.borderTop = border : bodyStyle.removeProperty("border-top");
_syncInterval = setInterval(_sync, 100);
gsap.delayedCall(0.5, function () {
return _startup = 0;
});
_addListener(_doc, "touchcancel", _passThrough);
_addListener(_body, "touchstart", _passThrough);
_multiListener(_addListener, _doc, "pointerdown,touchstart,mousedown", function () {
return _pointerIsDown = 1;
});
_multiListener(_addListener, _doc, "pointerup,touchend,mouseup", function () {
return _pointerIsDown = 0;
});
_transformProp = gsap.utils.checkPrefix("transform");
_stateProps.push(_transformProp);
_coreInitted = _getTime();
_resizeDelay = gsap.delayedCall(0.2, _refreshAll).pause();
_addListener(_doc, "visibilitychange", function () {
return _doc.hidden || _refreshAll();
});
_addListener(_doc, "DOMContentLoaded", _refreshAll);
_addListener(_win, "load", function () {
return _lastScrollTime || _refreshAll();
});
_addListener(_win, "resize", _onResize);
}
}
return _coreInitted;
};
ScrollTrigger.defaults = function defaults(config) {
for (var p in config) {
_defaults[p] = config[p];
}
};
ScrollTrigger.kill = function kill() {
_enabled = 0;
_triggers.slice(0).forEach(function (trigger) {
return trigger.kill(1);
});
};
ScrollTrigger.config = function config(vars) {
"limitCallbacks" in vars && (_limitCallbacks = !!vars.limitCallbacks);
var ms = vars.syncInterval;
ms && clearInterval(_syncInterval) || (_syncInterval = ms) && setInterval(_sync, ms);
};
return ScrollTrigger;
}();
ScrollTrigger.version = "3.3.4";
ScrollTrigger.create = function (vars, animation) {
return new ScrollTrigger(vars, animation);
};
ScrollTrigger.refresh = function (safe) {
return safe ? _onResize() : _refreshAll(true);
};
ScrollTrigger.update = _updateAll;
ScrollTrigger.maxScroll = function (element, horizontal) {
return _maxScroll(element, horizontal ? _horizontal : _vertical);
};
ScrollTrigger.getScrollFunc = function (element, horizontal) {
return (horizontal = horizontal ? _horizontal : _vertical) && (_isViewport(element) ? horizontal.sc : _getScrollFunc(element, horizontal));
};
ScrollTrigger.getById = function (id) {
return _ids[id];
};
ScrollTrigger.getAll = function () {
return _triggers.slice(0);
};
ScrollTrigger.isScrolling = function () {
return !!_lastScrollTime;
};
ScrollTrigger.addEventListener = function (type, callback) {
var a = _listeners[type] || (_listeners[type] = []);
~a.indexOf(callback) || a.push(callback);
};
ScrollTrigger.removeEventListener = function (type, callback) {
var a = _listeners[type],
i = a && a.indexOf(callback);
i >= 0 && a.splice(i, 1);
};
ScrollTrigger.batch = function (targets, vars) {
var result = [],
varsCopy = {},
interval = vars.interval || 0.016,
batchMax = vars.batchMax || 1e9,
proxyCallback = function proxyCallback(type, callback) {
var elements = [],
triggers = [],
delay = gsap.delayedCall(interval, function () {
callback(elements, triggers);
elements = [];
triggers = [];
}).pause();
return function (self) {
elements.length || delay.restart(true);
elements.push(self.trigger);
triggers.push(self);
batchMax <= elements.length && delay.progress(1);
};
},
p;
for (p in vars) {
varsCopy[p] = p.substr(0, 2) === "on" && _isFunction(vars[p]) && p !== "onRefreshInit" ? proxyCallback(p, vars[p]) : vars[p];
}
if (_isFunction(batchMax)) {
batchMax = batchMax();
_addListener(ScrollTrigger, "refresh", function () {
return batchMax = vars.batchMax();
});
}
_toArray(targets).forEach(function (target) {
var config = {};
for (p in varsCopy) {
config[p] = varsCopy[p];
}
config.trigger = target;
result.push(ScrollTrigger.create(config));
});
return result;
};
_getGSAP() && gsap.registerPlugin(ScrollTrigger);
exports.ScrollTrigger = ScrollTrigger;
exports.default = ScrollTrigger;
Object.defineProperty(exports, '__esModule', { value: true });
})));