scrollama
Version:
Lightweight scrollytelling library using IntersectionObserver
2 lines (1 loc) • 7.24 kB
JavaScript
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.scrollama=t()}(this,function(){"use strict";function e(e){return"scrollama__debug-offset--"+e}function t(t){!function(t){var n=t.id,r=t.offsetVal,o=t.stepClass,i=document.createElement("div");i.id=e(n),i.className="scrollama__debug-offset",i.style.position="fixed",i.style.left="0",i.style.width="100%",i.style.height="0",i.style.borderTop="2px dashed black",i.style.zIndex="9999";var s=document.createElement("p");s.innerText='".'+o+'" trigger: '+r,s.style.fontSize="12px",s.style.fontFamily="monospace",s.style.color="black",s.style.margin="0",s.style.padding="6px",i.appendChild(s),document.body.appendChild(i)}({id:t.id,offsetVal:t.offsetVal,stepClass:t.stepEl[0].className})}function n(e){var t=e.id,n=e.index,r=e.state,o="scrollama__debug-step--"+t+"-"+n,i=document.getElementById(o+"_above"),s=document.getElementById(o+"_below"),a="enter"===r?"block":"none";i&&(i.style.display=a),s&&(s.style.display=a)}return function(){var r=["stepAbove","stepBelow","stepProgress","viewportAbove","viewportBelow"],o={},i={},s=null,a=[],c=[],l=[],f=[],u=0,d=0,p=0,v=0,g=0,m=0,w=!1,b=!1,x=!1,h=!1,y=!1,E=!1,I="down",M=[];function A(){o={stepEnter:function(){},stepExit:function(){},stepProgress:function(){}},i={}}function C(e){return e.getBoundingClientRect().top+window.pageYOffset-(document.body.clientTop||0)}function O(e){return+e.getAttribute("data-scrollama-index")}function B(){window.pageYOffset>g?I="down":window.pageYOffset<g&&(I="up"),g=window.pageYOffset}function H(e){i[e]&&i[e].forEach(function(e){return e.disconnect()})}function N(){var t,n;p=window.innerHeight,t=document.body,n=document.documentElement,v=Math.max(t.scrollHeight,t.offsetHeight,n.clientHeight,n.scrollHeight,n.offsetHeight),d=u*p,w&&(c=a.map(function(e){return e.getBoundingClientRect().height}),l=a.map(C),b&&z()),x&&function(t){var n=t.id,r=t.offsetMargin,o=e(n);document.getElementById(o).style.top=r+"px"}({id:s,stepOffsetHeight:c,offsetMargin:d,offsetVal:u})}function S(e){if(e&&!b){if(!w)return console.error("scrollama error: enable() called before scroller was ready"),void(b=!1);z()}!e&&b&&r.forEach(H),b=e}function _(e,t){var n=O(e);void 0!==t&&(f[n].progress=t);var r={element:e,index:n,progress:f[n].progress};"enter"===f[n].state&&o.stepProgress(r)}function k(e,t){if("above"===t)for(var n=0;n<e;n+=1){var r=f[n];"enter"!==r.state&&"down"!==r.direction?(P(a[n],"down",!1),R(a[n],"down")):"enter"===r.state&&R(a[n],"down")}else if("below"===t)for(var o=f.length-1;o>e;o-=1){var i=f[o];"enter"===i.state&&R(a[o],"up"),"down"===i.direction&&(P(a[o],"up",!1),R(a[o],"up"))}}function P(e,t,r){void 0===r&&(r=!0);var i=O(e),a={element:e,index:i,direction:t};f[i].direction=t,f[i].state="enter",y&&r&&"down"===t&&k(i,"above"),y&&r&&"up"===t&&k(i,"below"),o.stepEnter&&!M[i]&&(o.stepEnter(a,f),x&&n({id:s,index:i,state:"enter"}),E&&(M[i]=!0)),h&&_(e)}function R(e,t){var r=O(e),i={element:e,index:r,direction:t};h&&("down"===t&&f[r].progress<1?_(e,1):"up"===t&&f[r].progress>0&&_(e,0)),f[r].direction=t,f[r].state="exit",o.stepExit(i,f),x&&n({id:s,index:r,state:"exit"})}function T(e){var t=e[0];B();var n=t.isIntersecting,r=t.boundingClientRect,o=t.target,i=r.top,s=r.bottom,a=i-d,c=s-d,l=O(o),u=f[l];n&&a<=0&&c>=0&&"down"===I&&"enter"!==u.state&&P(o,I),!n&&a>0&&"up"===I&&"enter"===u.state&&R(o,I)}function Y(e){var t=e[0];B();var n=t.isIntersecting,r=t.boundingClientRect,o=t.target,i=r.top,s=r.bottom,a=i-d,c=s-d,l=O(o),u=f[l];n&&a<=0&&c>=0&&"up"===I&&"enter"!==u.state&&P(o,I),!n&&c<0&&"down"===I&&"enter"===u.state&&R(o,I)}function q(e){var t=e[0];B();var n=t.isIntersecting,r=t.target,o=O(r),i=f[o];n&&"down"===I&&"down"!==i.direction&&"enter"!==i.state&&(P(r,"down"),R(r,"down"))}function V(e){var t=e[0];B();var n=t.isIntersecting,r=t.target,o=O(r),i=f[o];n&&"up"===I&&"down"===i.direction&&"enter"!==i.state&&(P(r,"up"),R(r,"up"))}function F(e){var t=e[0];B();var n=t.isIntersecting,r=t.intersectionRatio,o=t.boundingClientRect,i=t.target,s=o.bottom;n&&s-d>=0&&_(i,+r)}function j(){i.stepProgress=a.map(function(e,t){var n=c[t]-d+"px 0px "+(-p+d)+"px 0px",r=function(e){for(var t=Math.ceil(e/m),n=[],r=1/t,o=0;o<t;o+=1)n.push(o*r);return n}(c[t]),o=new IntersectionObserver(F,{rootMargin:n,threshold:r});return o.observe(e),o})}function z(){r.forEach(H),i.viewportAbove=a.map(function(e,t){var n=v-l[t],r=d-p-c[t],o=new IntersectionObserver(q,{rootMargin:n+"px 0px "+r+"px 0px"});return o.observe(e),o}),i.viewportBelow=a.map(function(e,t){var n=-d-c[t],r=d-p+c[t]+v,o=new IntersectionObserver(V,{rootMargin:n+"px 0px "+r+"px 0px"});return o.observe(e),o}),i.stepAbove=a.map(function(e,t){var n=-d+c[t],r=new IntersectionObserver(T,{rootMargin:n+"px 0px "+(d-p)+"px 0px"});return r.observe(e),r}),i.stepBelow=a.map(function(e,t){var n=-d,r=d-p+c[t],o=new IntersectionObserver(Y,{rootMargin:n+"px 0px "+r+"px 0px"});return o.observe(e),o}),h&&j()}function D(e){return!(!e||1!==e.nodeType)&&(function(e){var t=window.getComputedStyle(e);return("scroll"===t.overflowY||"auto"===t.overflowY)&&e.scrollHeight>e.clientHeight}(e)?e:D(e.parentNode))}var L={};return L.setup=function(e){var n=e.step,r=e.offset;void 0===r&&(r=.5);var o=e.progress;void 0===o&&(o=!1);var i=e.threshold;void 0===i&&(i=4);var c=e.debug;void 0===c&&(c=!1);var l=e.order;void 0===l&&(l=!0);var d,p,v,g,b,I=e.once;if(void 0===I&&(I=!1),A(),p=(d="abcdefghijklmnopqrstuv").length,v=Date.now(),s=""+[0,0,0].map(function(e){return d[Math.floor(Math.random()*p)]}).join("")+v,g=n,void 0===b&&(b=document),!(a="string"==typeof g?Array.from(b.querySelectorAll(g)):g instanceof Element?[g]:g instanceof NodeList?Array.from(g):g instanceof Array?g:[]).length)return console.error("scrollama error: no step elements"),L;var M=a.reduce(function(e,t){return e||D(t.parentNode)},!1);return M&&console.error("scrollama error: step elements cannot be children of a scrollable element. Remove any css on the parent element with overflow: scroll; or overflow: auto; on elements with fixed height.",M),x=c,h=o,y=l,E=I,L.offsetTrigger(r),m=Math.max(1,+i),w=!0,x&&t({id:s,stepEl:a,offsetVal:u}),a.forEach(function(e,t){return e.setAttribute("data-scrollama-index",t)}),f=a.map(function(){return{direction:null,state:null,progress:0}}),N(),L.enable(),L},L.resize=function(){return N(),L},L.enable=function(){return S(!0),L},L.disable=function(){return S(!1),L},L.destroy=function(){S(!1),A()},L.offsetTrigger=function(e){return e&&!isNaN(e)?(e>1&&console.error("scrollama error: offset value is greater than 1. Fallbacks to 1."),e<0&&console.error("scrollama error: offset value is lower than 0. Fallbacks to 0."),u=Math.min(Math.max(0,e),1),L):(isNaN(e)&&console.error("scrollama error: offset value is not a number. Fallbacks to 0."),u)},L.onStepEnter=function(e){return"function"==typeof e?o.stepEnter=e:console.error("scrollama error: onStepEnter requires a function"),L},L.onStepExit=function(e){return"function"==typeof e?o.stepExit=e:console.error("scrollama error: onStepExit requires a function"),L},L.onStepProgress=function(e){return"function"==typeof e?o.stepProgress=e:console.error("scrollama error: onStepProgress requires a function"),L},L}});