react-just-parallax
Version:
React library for scroll and mousemove parallax effect ✨ Open source, production-ready
3 lines (2 loc) • 13 kB
JavaScript
import e,{useState as t,useRef as n,useCallback as r,useEffect as i,forwardRef as s,useImperativeHandle as o}from"react";const u="undefined"!=typeof performance?()=>performance.now():()=>Date.now(),c="undefined"!=typeof window?e=>window.requestAnimationFrame(e):e=>setTimeout((()=>e(u())),16.666666666666668);let l=!0,a=!1,d=!1;const h={delta:0,timestamp:0},f=["read","update","preRender","render","postRender"],v=f.reduce(((e,t)=>(e[t]=function(e){let t=[],n=[],r=0,i=!1,s=!1;const o=new WeakSet,u={schedule:(e,s=!1,u=!1)=>{const c=u&&i,l=c?t:n;return s&&o.add(e),-1===l.indexOf(e)&&(l.push(e),c&&i&&(r=t.length)),e},cancel:e=>{const t=n.indexOf(e);-1!==t&&n.splice(t,1),o.delete(e)},process:c=>{if(i)s=!0;else{if(i=!0,[t,n]=[n,t],n.length=0,r=t.length,r)for(let n=0;n<r;n++){const r=t[n];r(c),o.has(r)&&(u.schedule(r),e())}i=!1,s&&(s=!1,u.process(c))}}};return u}((()=>a=!0)),e)),{}),p=f.reduce(((e,t)=>{const n=v[t];return e[t]=(e,t=!1,r=!1)=>(a||E(),n.schedule(e,t,r)),e}),{}),w=f.reduce(((e,t)=>(e[t]=v[t].cancel,e)),{});f.reduce(((e,t)=>(e[t]=()=>v[t].process(h),e)),{});const m=e=>v[e].process(h),y=e=>{a=!1,h.delta=l?16.666666666666668:Math.max(Math.min(e-h.timestamp,40),1),h.timestamp=e,d=!0,f.forEach(m),d=!1,a&&(l=!1,c(y))},E=()=>{a=!0,l=!0,d||c(y)};var g="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},_=/^\s+|\s+$/g,x=/^[-+]0x[0-9a-f]+$/i,L=/^0b[01]+$/i,b=/^0o[0-7]+$/i,O=parseInt,T="object"==typeof g&&g&&g.Object===Object&&g,M="object"==typeof self&&self&&self.Object===Object&&self,W=T||M||Function("return this")(),z=Object.prototype.toString,U=Math.max,S=Math.min,H=function(){return W.Date.now()};function R(e){var t=typeof e;return!!e&&("object"==t||"function"==t)}function C(e){if("number"==typeof e)return e;if(function(e){return"symbol"==typeof e||function(e){return!!e&&"object"==typeof e}(e)&&"[object Symbol]"==z.call(e)}(e))return NaN;if(R(e)){var t="function"==typeof e.valueOf?e.valueOf():e;e=R(t)?t+"":t}if("string"!=typeof e)return 0===e?e:+e;e=e.replace(_,"");var n=L.test(e);return n||b.test(e)?O(e.slice(2),n?2:8):x.test(e)?NaN:+e}var j=function(e,t,n){var r,i,s,o,u,c,l=0,a=!1,d=!1,h=!0;if("function"!=typeof e)throw new TypeError("Expected a function");function f(t){var n=r,s=i;return r=i=void 0,l=t,o=e.apply(s,n)}function v(e){return l=e,u=setTimeout(w,t),a?f(e):o}function p(e){var n=e-c;return void 0===c||n>=t||n<0||d&&e-l>=s}function w(){var e=H();if(p(e))return m(e);u=setTimeout(w,function(e){var n=t-(e-c);return d?S(n,s-(e-l)):n}(e))}function m(e){return u=void 0,h&&r?f(e):(r=i=void 0,o)}function y(){var e=H(),n=p(e);if(r=arguments,i=this,c=e,n){if(void 0===u)return v(c);if(d)return u=setTimeout(w,t),f(c)}return void 0===u&&(u=setTimeout(w,t)),o}return t=C(t)||0,R(n)&&(a=!!n.leading,s=(d="maxWait"in n)?U(C(n.maxWait)||0,t):s,h="trailing"in n?!!n.trailing:h),y.cancel=function(){void 0!==u&&clearTimeout(u),l=0,r=c=i=u=void 0},y.flush=function(){return void 0===u?o:m(H())},y},D={exports:{}},$="undefined"!=typeof document?document.createElement("p").style:{},k=["O","ms","Moz","Webkit"],I=/([A-Z])/g,X={};function Y(e){if(e=e.replace(/-([a-z])/g,(function(e,t){return t.toUpperCase()})),void 0!==$[e])return e;for(var t=e.charAt(0).toUpperCase()+e.slice(1),n=k.length;n--;){var r=k[n]+t;if(void 0!==$[r])return r}return e}D.exports=function(e){return e in X?X[e]:X[e]=Y(e)},D.exports.dash=function(e){return e=Y(e),I.test(e)&&(e="-"+e.replace(I,"-$1"),I.lastIndex=0),e.toLowerCase()};const P={isReady:!1,scrollbarWidth:0,windowHeight:0,windowWidth:0},A=()=>{const[e,s]=t(P),o=n(P),u=r((()=>{const e={isReady:!0,scrollbarWidth:window.innerWidth-document.documentElement.clientWidth,windowHeight:window.innerHeight,windowWidth:window.innerWidth};s(e),o.current=e}),[]);return i((()=>{const e=j(u,100);return window.addEventListener("resize",e),u(),()=>{window.removeEventListener("resize",e)}}),[u]),{windowSize:e,windowSizeRef:o}},F=(e,t,n)=>e+(t-e)*n;class N extends class{addEventListener(e,t){void 0===this._listeners&&(this._listeners={});const n=this._listeners;void 0===n[e]&&(n[e]=[]),-1===n[e].indexOf(t)&&n[e].push(t)}hasEventListener(e,t){if(void 0===this._listeners)return!1;const n=this._listeners;return void 0!==n[e]&&-1!==n[e].indexOf(t)}removeEventListener(e,t){if(void 0===this._listeners)return;const n=this._listeners[e];if(void 0!==n){const e=n.indexOf(t);-1!==e&&n.splice(e,1)}}dispatchEvent(e){if(void 0===this._listeners)return;const t=this._listeners[e.type];if(void 0!==t){e.target=this;const n=t.slice(0);for(let t=0,r=n.length;t<r;t++)n[t].call(this,e);e.target=null}}}{constructor(){super(),this._mouseLast={x:0,y:0},this._isTouching=!1,this.mouse={x:0,y:0},this._shouldUpdate=!1,this._onTouchDown=e=>{this._shouldUpdate&&(this._isTouching=!0,this._mouseLast.x="touches"in e?e.touches[0].clientX:e.clientX,this._mouseLast.y="touches"in e?e.touches[0].clientY:e.clientY,this.mouse.x=this._mouseLast.x,this.mouse.y=this._mouseLast.y,this.dispatchEvent({type:"down"}),this.dispatchEvent({type:"mousemove"}))},this._onTouchMove=e=>{if(!this._shouldUpdate)return;const t="touches"in e?e.touches[0].clientX:e.clientX,n="touches"in e?e.touches[0].clientY:e.clientY,r=t-this._mouseLast.x,i=n-this._mouseLast.y;this._mouseLast.x=t,this._mouseLast.y=n,this.mouse.x+=r,this.mouse.y+=i,this.dispatchEvent({type:"mousemove"})},this._onTouchUp=()=>{this._shouldUpdate&&(this._isTouching=!1,this.dispatchEvent({type:"up"}),this.dispatchEvent({type:"mousemove"}))},this._onMouseLeave=()=>{this.dispatchEvent({type:"left"})}}_addEvents(){this._targetEl.addEventListener("mousedown",this._onTouchDown),this._targetEl.addEventListener("mousemove",this._onTouchMove,{passive:!0}),this._targetEl.addEventListener("mouseup",this._onTouchUp),this._targetEl.addEventListener("touchstart",this._onTouchDown,{passive:!0}),this._targetEl.addEventListener("touchmove",this._onTouchMove,{passive:!0}),this._targetEl.addEventListener("touchend",this._onTouchUp),this._targetEl.addEventListener("mouseout",this._onMouseLeave)}_removeEvents(){this._targetEl.removeEventListener("mousedown",this._onTouchDown),this._targetEl.removeEventListener("mousemove",this._onTouchMove),this._targetEl.removeEventListener("mouseup",this._onTouchUp),this._targetEl.removeEventListener("touchstart",this._onTouchDown),this._targetEl.removeEventListener("touchmove",this._onTouchMove),this._targetEl.removeEventListener("touchend",this._onTouchUp),this._targetEl.removeEventListener("mouseout",this._onMouseLeave)}init(e){this._targetEl=window,e&&e.current&&(this._targetEl=e.current),this._addEvents()}destroy(){this._removeEvents()}setShouldUpdate(e){this._shouldUpdate=e}update(){this._mouseLast.x=this.mouse.x,this._mouseLast.y=this.mouse.y}}const V=()=>"undefined"!=typeof window&&("ontouchstart"in window||"ontouchstart"in document.documentElement||navigator.maxTouchPoints>0),B={height:1,width:1,x:1,y:1},q=t=>{const{children:r,strength:s=.14,parallaxContainerRef:o=null,scrollContainerRef:u=null,shouldResetPosition:c=!1,enableOnTouchDevice:l=!1,isAbsolutelyPositioned:a=!1,lerpEase:d=.06,zIndex:h=null,shouldPause:f=!0}=t,{windowSizeRef:v}=A(),m=n(null),y=n(null),E=n(0),g=n(0),_=n(0),x=n(0),L=n(null),b=n(null),O=n(!0),T=n(B),M=n(new N),W=n(null),z=n(D.exports("transform")),U=()=>{O.current&&m.current&&(m.current.style.willChange="transform",L.current=p.render(H,!0),b.current=p.update(R,!0))},S=()=>{m.current&&(m.current.style.willChange="auto",L.current&&w.render(L.current),b.current&&w.update(b.current))},H=()=>{if(!m.current)return;let e=v.current.windowWidth,t=v.current.windowHeight;o&&o.current&&(e=T.current.width,t=T.current.height),e*=.5,t*=.5,e*=s,t*=s,m.current.style[z.current]=`translate3d(${E.current*e}px, ${g.current*t}px, 0px)`},R=({delta:e})=>{const t=Math.abs(_.current-E.current),n=Math.abs(x.current-g.current);if(t<.001&&n<.001)return;let r=e/16.666666666666668;M.current.update();const i=Math.round(r);i>=1&&(r=i);const s=F(E.current,_.current,d*r);E.current=s;const o=F(g.current,x.current,d*r);g.current=o},C=()=>{document.hidden?S():U()},$=(e,t)=>{let n=v.current.windowWidth,r=v.current.windowHeight,i=e,s=t;return o&&o.current&&(n=T.current.width,r=T.current.height,i=e-T.current.x,s=t-T.current.y),{x:i/n*2-1,y:s/r*2-1}},k=e=>{const t=e.target.mouse.x,n=e.target.mouse.y,{x:r,y:i}=$(t,n);_.current=r,x.current=i},I=()=>{c&&(_.current=0,x.current=0)},X=e=>{const t="touches"in e?e.touches[0].clientX:e.clientX,n="touches"in e?e.touches[0].clientY:e.clientY,{x:r,y:i}=$(t,n);(r<=-1||r>=1||i>=1||i<=-1)&&I()},Y=()=>{if(!o||!o.current)return;const e=o.current.getBoundingClientRect();T.current={x:e.x,y:e.y,width:o.current.clientWidth,height:o.current.clientHeight}},P=j(Y,150),q=e=>{if(e[0].isIntersecting)O.current=!0,U(),M.current.setShouldUpdate(!0);else{if(!f)return;O.current=!1,S(),M.current.setShouldUpdate(!1)}};return i((()=>{if(!l&&V())return;M.current.init(o),U();let e=window,t=window;return u&&u.current&&(t=u.current),o&&o.current&&(Y(),e=o.current,t.addEventListener("scroll",P,{passive:!0}),window.addEventListener("resize",P,{passive:!0})),M.current.addEventListener("mousemove",k),window.addEventListener("visibilitychange",C),window.addEventListener("touchstart",X,{passive:!0}),e.addEventListener("mouseout",I),W.current=new IntersectionObserver(q,{threshold:.5}),y.current&&W.current.observe(y.current),()=>{S(),o&&o.current&&(t.removeEventListener("scroll",P),window.removeEventListener("resize",P)),M.current.removeEventListener("mousemove",k),window.removeEventListener("visibilitychange",C),window.removeEventListener("touchstart",X),e.removeEventListener("mouseout",I),y.current&&W.current&&W.current.unobserve(y.current),M.current.destroy()}}),[]),e.createElement(e.Fragment,null,e.createElement("span",{ref:y,style:{width:"100%",height:"100%",display:"inline-block",userSelect:"none",pointerEvents:"none",position:a?"absolute":"relative",top:0,left:0,zIndex:h||"initial"}},e.createElement("span",{ref:m,style:{backfaceVisibility:"hidden",position:"relative",width:"100%",height:"100%",display:"inline-block",userSelect:"initial",pointerEvents:"initial"}},r)))},Z={xMaxOffset:1,xOffset:1,yMaxOffset:1,yOffset:1},G=s(((t,r)=>{o(r,(()=>({updateValues:k})));const{children:s,strength:u=.14,scrollContainerRef:c=null,enableOnTouchDevice:l=!0,lerpEase:a=.06,isHorizontal:d=!1,isAbsolutelyPositioned:h=!1,zIndex:f=null,shouldPause:v=!0}=t,m=n(null),y=n(null),E=n(1),g=n(1),_=n(1),x=n(1),L=n(null),b=n(null),O=n(!0),T=n(Z),M=n(1),W=n(1),{windowSizeRef:z}=A(),U=n(D.exports("transform")),S=()=>{m.current&&(m.current.style.willChange="transform",L.current=p.render(R,!0),b.current=p.update(C,!0))},H=()=>{m.current&&(m.current.style.willChange="auto",L.current&&w.render(L.current),b.current&&w.update(b.current))},R=()=>{if(!O.current)return;if(!m.current)return;let e=d?1:0;m.current.style[U.current]=`translate3d(${E.current*u*e}px, ${g.current*u*(1-e)}px, 0px)`},C=({delta:e})=>{if(!O.current)return;const t=Math.abs(_.current-E.current),n=Math.abs(x.current-g.current);if(t<.001&&n<.001)return;let r=e/16.666666666666668;const i=Math.round(r);i>=1&&(r=i);const s=F(E.current,_.current,a*r);E.current=s;const o=F(g.current,x.current,a*r);g.current=o},$=()=>{document.hidden?H():S()},k=()=>{(()=>{if(!y||!y.current)return;X();const e=y.current.getBoundingClientRect();M.current=T.current.xOffset+e.x+.5*e.width,W.current=T.current.yOffset+e.y+.5*e.height})(),Y()},I=j(k,150),X=()=>{var e;c&&c.current?T.current={xOffset:(e=c.current).scrollLeft,yOffset:e.scrollTop,xMaxOffset:e.scrollWidth-e.offsetWidth,yMaxOffset:e.scrollHeight-e.offsetHeight}:T.current={xOffset:window.pageXOffset,yOffset:window.pageYOffset,xMaxOffset:document.body.clientWidth-window.innerWidth,yMaxOffset:document.body.clientHeight-window.innerHeight}},Y=()=>{X();let e=T.current.xOffset-M.current,t=T.current.yOffset-W.current;if(e+=.5*z.current.windowWidth,t+=.5*z.current.windowHeight,_.current=e,x.current=t,Math.abs(x.current)>1.5*z.current.windowHeight||Math.abs(_.current)>1.5*z.current.windowWidth){if(!v)return;O.current=!1}else O.current=!0};return i((()=>{if(!l&&V())return;S();let e=window;return c&&c.current&&(e=c.current),e.addEventListener("scroll",Y,{passive:!0}),window.addEventListener("visibilitychange",$),window.addEventListener("resize",I),k(),()=>{H(),e.removeEventListener("scroll",Y),window.removeEventListener("visibilitychange",$),window.removeEventListener("resize",I)}}),[]),e.createElement(e.Fragment,null,e.createElement("span",{ref:y,style:{width:"100%",height:"100%",display:"inline-block",userSelect:"none",pointerEvents:"none",position:h?"absolute":"relative",top:0,left:0,zIndex:f||"initial"}},e.createElement("span",{ref:m,style:{backfaceVisibility:"hidden",position:"relative",width:"100%",height:"100%",display:"inline-block",userSelect:"initial",pointerEvents:"initial"}},s)))}));export{q as MouseParallax,G as ScrollParallax};
//# sourceMappingURL=index.js.map