UNPKG

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
(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 }); })));