Skip to content

Instantly share code, notes, and snippets.

@dianaow
Created April 9, 2019 05:37
Show Gist options
  • Save dianaow/2397f2ab748895027869dfe9f0153d82 to your computer and use it in GitHub Desktop.
Save dianaow/2397f2ab748895027869dfe9f0153d82 to your computer and use it in GitHub Desktop.
Template: Scrollytelling with enter-view.js
license: mit
"use strict";!function(e){"function"==typeof define&&define.amd?define(e):"undefined"!=typeof module&&module.exports?module.exports=e():window.enterView=e.call(this)}(function(){var e=function(e){function n(){E=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame||function(e){return setTimeout(e,1e3/60)}}function t(){if(y&&"number"==typeof y){var e=Math.min(Math.max(0,y),1);return F-e*F}return F}function o(){var e=document.documentElement.clientHeight,n=window.innerHeight||0;F=Math.max(e,n)}function r(){L=!1;var e=t();M=M.filter(function(n){var t=n.getBoundingClientRect(),o=t.top,r=t.bottom,i=t.height,s=o<e,u=r<e;if(s&&!n.__ev_entered){if(m(n),n.__ev_progress=0,h(n,n.__ev_progress),q)return!1}else!s&&n.__ev_entered&&(n.__ev_progress=0,h(n,n.__ev_progress),g(n));if(s&&!u){var d=(e-o)/i;n.__ev_progress=Math.min(1,Math.max(0,d)),h(n,n.__ev_progress)}return s&&u&&1!==n.__ev_progress&&(n.__ev_progress=1,h(n,n.__ev_progress)),n.__ev_entered=s,!0}),M.length||window.removeEventListener("scroll",i,!0)}function i(){L||(L=!0,E(r))}function s(){o(),r()}function u(){o(),r()}function d(e){for(var n=e.length,t=[],o=0;o<n;o+=1)t.push(e[o]);return t}function f(e){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:document;return"string"==typeof e?d(n.querySelectorAll(e)):e instanceof NodeList?d(e):e instanceof Array?e:void 0}function c(){M=f(v)}function a(){window.addEventListener("resize",s,!0),window.addEventListener("scroll",i,!0),window.addEventListener("load",u,!0),s()}function _(){return v?(c(),M&&M.length?(n(),a(),void r()):(console.error("no selector elements found"),!1)):(console.error("must pass a selector"),!1)}var v=e.selector,l=e.enter,m=void 0===l?function(){}:l,w=e.exit,g=void 0===w?function(){}:w,p=e.progress,h=void 0===p?function(){}:p,x=e.offset,y=void 0===x?0:x,A=e.once,q=void 0!==A&&A,E=null,L=!1,M=[],F=0;_()};return e});
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="description" content="">
<meta name="viewport" content="width=device-width">
<title>scrollytelling</title>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="stickyfill.min.js"></script>
<script src="enter-view.min.js"></script>
<link rel="stylesheet" href="scrollytelly.css">
</head>
<body>
<section id='scrolly-side'>
<div class='scrolly'>
<article>
<div class='step' data-width='10%' data-index='0'><p>Bar is 10%</p></div>
<div class='step' data-width='90%' data-index='1'><p>Bar is 90%</p></div>
<div class='step' data-width='50%' data-index='2'><p>Bar is 50%</p></div>
</article>
<figure class='sticky'>
<div class='bar-outer'>
<div class='bar-inner'></div>
</div>
</figure>
</div>
</section>
<!-- Scripts -->
<script>
const container = d3.select('#scrolly-side');
const stepSel = container.selectAll('.step');
function updateChart(index) {
const sel = container.select(`[data-index='${index}']`);
const width = sel.attr('data-width');
stepSel.classed('is-active', (d, i) => i === index);
container.select('.bar-inner').style('width', width);
}
function init() {
Stickyfill.add(d3.select('.sticky').node());
enterView({
selector: stepSel.nodes(),
offset: 0.5,
enter: el => {
const index = +d3.select(el).attr('data-index');
updateChart(index);
},
exit: el => {
let index = +d3.select(el).attr('data-index');
index = Math.max(0, index - 1);
updateChart(index);
}
});
}
init()
</script>
</body>
</html>
#scrolly-side .scrolly {
display: flex;
max-width: 60rem;
margin: 3rem auto;
background-color: cornsilk;
padding: 1rem;
}
* {
flex: 1;
}
article {
padding-right: 1rem;
max-width: 30rem;
}
.step {
min-height: 67vh;
margin-bottom: 1rem;
background-color: white;
transition: background-color 250ms ease-in-out;
}
.step:last-of-type {
margin-bottom: 0;
}
.step.is-active {
background-color: gray;
}
}
article > p {
margin: 0;
padding: 1rem;
text-align: center;
font-weight: 400;
color: black;
}
figure.sticky {
position: sticky;
width: 100%;
height: 50vh;
background: silver;
margin: 0;
top: 25vh;
left: 0;
}
.bar-outer {
position: absolute;
top: 50%;
left: 5%;
transform: translateY(-50%);
width: 90%;
height: 4rem;
background-color: green;
}
.bar-inner {
width: 10%;
height: 100%;
transition: width 1s ease-in-out;
background-color: red;
}
/*!
* Stickyfill – `position: sticky` polyfill
* v. 2.1.0 | https://github.com/wilddeer/stickyfill
* MIT License
*/
!function(a,b){"use strict";function c(a,b){if(!(a instanceof b))throw new TypeError("Cannot call a class as a function")}function d(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c])}function e(a){return parseFloat(a)||0}function f(a){for(var b=0;a;)b+=a.offsetTop,a=a.offsetParent;return b}function g(){function c(){a.pageXOffset!=m.left?(m.top=a.pageYOffset,m.left=a.pageXOffset,p.refreshAll()):a.pageYOffset!=m.top&&(m.top=a.pageYOffset,m.left=a.pageXOffset,n.forEach(function(a){return a._recalcPosition()}))}function d(){f=setInterval(function(){n.forEach(function(a){return a._fastCheck()})},500)}function e(){clearInterval(f)}if(!k){k=!0,c(),a.addEventListener("scroll",c),a.addEventListener("resize",p.refreshAll),a.addEventListener("orientationchange",p.refreshAll);var f=void 0,g=void 0,h=void 0;"hidden"in b?(g="hidden",h="visibilitychange"):"webkitHidden"in b&&(g="webkitHidden",h="webkitvisibilitychange"),h?(b[g]||d(),b.addEventListener(h,function(){b[g]?e():d()})):d()}}var h=function(){function a(a,b){for(var c=0;c<b.length;c++){var d=b[c];d.enumerable=d.enumerable||!1,d.configurable=!0,"value"in d&&(d.writable=!0),Object.defineProperty(a,d.key,d)}}return function(b,c,d){return c&&a(b.prototype,c),d&&a(b,d),b}}(),i=!1,j="undefined"!=typeof a;j&&a.getComputedStyle?!function(){var a=b.createElement("div");["","-webkit-","-moz-","-ms-"].some(function(b){try{a.style.position=b+"sticky"}catch(a){}return""!=a.style.position})&&(i=!0)}():i=!0;var k=!1,l="undefined"!=typeof ShadowRoot,m={top:null,left:null},n=[],o=function(){function g(a){if(c(this,g),!(a instanceof HTMLElement))throw new Error("First argument must be HTMLElement");if(n.some(function(b){return b._node===a}))throw new Error("Stickyfill is already applied to this node");this._node=a,this._stickyMode=null,this._active=!1,n.push(this),this.refresh()}return h(g,[{key:"refresh",value:function(){if(!i&&!this._removed){this._active&&this._deactivate();var c=this._node,g=getComputedStyle(c),h={position:g.position,top:g.top,display:g.display,marginTop:g.marginTop,marginBottom:g.marginBottom,marginLeft:g.marginLeft,marginRight:g.marginRight,cssFloat:g.cssFloat};if(!isNaN(parseFloat(h.top))&&"table-cell"!=h.display&&"none"!=h.display){this._active=!0;var j=c.style.position;"sticky"!=g.position&&"-webkit-sticky"!=g.position||(c.style.position="static");var k=c.parentNode,m=l&&k instanceof ShadowRoot?k.host:k,n=c.getBoundingClientRect(),o=m.getBoundingClientRect(),p=getComputedStyle(m);this._parent={node:m,styles:{position:m.style.position},offsetHeight:m.offsetHeight},this._offsetToWindow={left:n.left,right:b.documentElement.clientWidth-n.right},this._offsetToParent={top:n.top-o.top-e(p.borderTopWidth),left:n.left-o.left-e(p.borderLeftWidth),right:-n.right+o.right-e(p.borderRightWidth)},this._styles={position:j,top:c.style.top,bottom:c.style.bottom,left:c.style.left,right:c.style.right,width:c.style.width,marginTop:c.style.marginTop,marginLeft:c.style.marginLeft,marginRight:c.style.marginRight};var q=e(h.top);this._limits={start:n.top+a.pageYOffset-q,end:o.top+a.pageYOffset+m.offsetHeight-e(p.borderBottomWidth)-c.offsetHeight-q-e(h.marginBottom)};var r=p.position;"absolute"!=r&&"relative"!=r&&(m.style.position="relative"),this._recalcPosition();var s=this._clone={};s.node=b.createElement("div"),d(s.node.style,{width:n.right-n.left+"px",height:n.bottom-n.top+"px",marginTop:h.marginTop,marginBottom:h.marginBottom,marginLeft:h.marginLeft,marginRight:h.marginRight,cssFloat:h.cssFloat,padding:0,border:0,borderSpacing:0,fontSize:"1em",position:"static"}),k.insertBefore(s.node,c),s.docOffsetTop=f(s.node)}}}},{key:"_recalcPosition",value:function(){if(this._active&&!this._removed){var a=m.top<=this._limits.start?"start":m.top>=this._limits.end?"end":"middle";if(this._stickyMode!=a){switch(a){case"start":d(this._node.style,{position:"absolute",left:this._offsetToParent.left+"px",right:this._offsetToParent.right+"px",top:this._offsetToParent.top+"px",bottom:"auto",width:"auto",marginLeft:0,marginRight:0,marginTop:0});break;case"middle":d(this._node.style,{position:"fixed",left:this._offsetToWindow.left+"px",right:this._offsetToWindow.right+"px",top:this._styles.top,bottom:"auto",width:"auto",marginLeft:0,marginRight:0,marginTop:0});break;case"end":d(this._node.style,{position:"absolute",left:this._offsetToParent.left+"px",right:this._offsetToParent.right+"px",top:"auto",bottom:0,width:"auto",marginLeft:0,marginRight:0})}this._stickyMode=a}}}},{key:"_fastCheck",value:function(){this._active&&!this._removed&&(Math.abs(f(this._clone.node)-this._clone.docOffsetTop)>1||Math.abs(this._parent.node.offsetHeight-this._parent.offsetHeight)>1)&&this.refresh()}},{key:"_deactivate",value:function(){var a=this;this._active&&!this._removed&&(this._clone.node.parentNode.removeChild(this._clone.node),delete this._clone,d(this._node.style,this._styles),delete this._styles,n.some(function(b){return b!==a&&b._parent&&b._parent.node===a._parent.node})||d(this._parent.node.style,this._parent.styles),delete this._parent,this._stickyMode=null,this._active=!1,delete this._offsetToWindow,delete this._offsetToParent,delete this._limits)}},{key:"remove",value:function(){var a=this;this._deactivate(),n.some(function(b,c){if(b._node===a._node)return n.splice(c,1),!0}),this._removed=!0}}]),g}(),p={stickies:n,Sticky:o,forceSticky:function(){i=!1,g(),this.refreshAll()},addOne:function(a){if(!(a instanceof HTMLElement)){if(!a.length||!a[0])return;a=a[0]}for(var b=0;b<n.length;b++)if(n[b]._node===a)return n[b];return new o(a)},add:function(a){if(a instanceof HTMLElement&&(a=[a]),a.length){for(var b=[],c=function(c){var d=a[c];return d instanceof HTMLElement?n.some(function(a){if(a._node===d)return b.push(a),!0})?"continue":void b.push(new o(d)):(b.push(void 0),"continue")},d=0;d<a.length;d++){c(d)}return b}},refreshAll:function(){n.forEach(function(a){return a.refresh()})},removeOne:function(a){if(!(a instanceof HTMLElement)){if(!a.length||!a[0])return;a=a[0]}n.some(function(b){if(b._node===a)return b.remove(),!0})},remove:function(a){if(a instanceof HTMLElement&&(a=[a]),a.length)for(var b=function(b){var c=a[b];n.some(function(a){if(a._node===c)return a.remove(),!0})},c=0;c<a.length;c++)b(c)},removeAll:function(){for(;n.length;)n[0].remove()}};i||g(),"undefined"!=typeof module&&module.exports?module.exports=p:j&&(a.Stickyfill=p)}(window,document);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment