Built with blockbuilder.org
Last active
July 28, 2017 15:13
-
-
Save baronwatts/2a50ae537d7c46670aa5eb30254ef751 to your computer and use it in GitHub Desktop.
ScrollyTelling Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
license: mit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<script src="https://d3js.org/d3.v3.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/waypoints/4.0.1/noframework.waypoints.js"></script> | |
<style> | |
@import url('https://fonts.googleapis.com/css?family=Open+Sans:300,600'); | |
*{ | |
margin:0; | |
padding:0; | |
} | |
html, | |
body{ | |
height: 100%; | |
padding: 0; | |
scroll-behavior: smooth; | |
background: #f7f5f2; | |
color: #666; | |
font-family: 'Open Sans', sans-serif; | |
font-weight: 300; | |
} | |
h2{ | |
line-height: 1.25; | |
padding-top: 45px; | |
font-weight: 300; | |
} | |
svg{ | |
padding: 20px; | |
} | |
text{ | |
font-size: 10px; | |
} | |
strong{ | |
font-weight: 600; | |
} | |
#graphic { | |
max-width: 1440px; | |
width: 100%; | |
position: relative; | |
height: 100%; | |
position: relative; | |
margin:auto; | |
} | |
.container { | |
height: 100%; | |
max-width: 440px; | |
width: 100%; | |
margin: 0; | |
padding: 0; | |
position: absolute; | |
height: 100%; | |
line-height: 1.5; | |
left: 500px; | |
} | |
.container div { | |
height: 100%; | |
display: block; | |
padding: 0 45px; | |
} | |
.fixed { | |
position: fixed; | |
max-width: 500px; | |
height: 500px; | |
top: 50px; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="graphic"> | |
<div class="container"> | |
<div id="div1"> | |
<h2>On <strong>July 27, 2017</strong> there were <strong>20</strong> people attending the Data Visualization meetup.</h2> | |
</div> | |
<div id="div2"> | |
<h2>Out of those <strong>20</strong> there were <strong>12</strong> people who attended.</h2> | |
<p></p> | |
</div> | |
<div id="div4"> | |
<h2><strong>5</strong> out of <strong>12</strong> people had iphones. The other <strong>7</strong> had android devices</h2> | |
</div> | |
<div id="div6"> | |
<h2>Out of those <strong>12</strong> attendees only <strong>3</strong> people were San Diego natives. <br><br>The age group for the attendees ranged between 25 and 65.</h2> | |
</div> | |
</div> | |
<!-- svg --> | |
<div class="fixed"><svg id="viz" width="100%" height="100%"></svg></div> | |
</div><!-- /graphic --> | |
<script> | |
//svg | |
let svg = d3.select("svg"); | |
//svg width and height | |
svg.attr('width',500) | |
.attr('height',500) | |
//set up grid spacing | |
let spacing = 40; | |
let rows = 10; | |
let column = 10; | |
let randnum = (min,max) => Math.round( Math.random() * (max-min) + min ); | |
//Create an array of objects | |
let our_data = d3.range(20).map(i => | |
({ 'device': i < 5 ? 'ios' : 'android', | |
'city': i < 3 ? 'San Diegan' : 'Out of towners', | |
'age': randnum(25, 65) | |
})); | |
//create group and join our data to that group | |
let group = svg.selectAll('g') | |
.data(our_data) | |
.enter() | |
.append("g") | |
//create rectangles | |
let rects = group.append("rect") | |
//city data | |
d3.selectAll('g') | |
.append("text") | |
.text( (d) => d["city"]) | |
.attr("fill", "gray") | |
.attr("class", "city") | |
.attr("dx", -500) | |
//age data | |
d3.selectAll('g') | |
.append("text") | |
.text( (d) => d["age"] ) | |
.attr("fill", "#fff") | |
.attr("class", "age") | |
.attr("dx", -500) | |
// square grid | |
let grid = () =>{ | |
rects | |
.transition() | |
.delay((d, i) => 10 * i) | |
.duration(600) | |
.ease("elastic") | |
.attr("width", 20) | |
.attr("height", 20) | |
.attr("rx", 5) | |
.attr("ry", 5) | |
.attr("x", (d, i) => i % column * spacing) | |
.attr("y", (d, i) => Math.floor(i / 10) % rows * spacing) | |
.attr("fill", (d, i) => (i < 40 ? "#394147" : "#99c125")) | |
.attr("opacity", "1") | |
} | |
//circle grid | |
let grid2 = () =>{ | |
rects | |
.transition() | |
.delay((d, i) => 10 * i) | |
.duration(600) | |
.ease("elastic") | |
.attr("width", 20) | |
.attr("height", 20) | |
.attr("rx", "50%") | |
.attr("ry", "50%") | |
.attr("x", (d, i) => i % column * spacing) | |
.attr("y", (d, i) => Math.floor(i / 10) % rows * spacing) | |
.attr("fill", (d, i) => (i < 8 ? "none" : "#99c125")) | |
} | |
//divide | |
let divide = () =>{ | |
rects | |
.transition() | |
.delay((d, i) => 10 * i) | |
.duration(600) | |
.ease("elastic") | |
.attr("width", 10) | |
.attr("height", 10) | |
.attr("rx", 0) | |
.attr("ry", 0) | |
.attr("x", (d, i) => d['device'] == "ios" ? randnum(100, 150) : randnum(300, 350)) | |
.attr("y", (d, i) => i * 20) | |
.attr("fill", (d, i) => d['device'] == "ios" ? "#394147": "#99c125") | |
.attr("opacity", (d,i)=> i < 12 ? 1 : 0 )//only show 12 people | |
//age | |
d3.selectAll('text.age') | |
.transition() | |
.delay( (d,i) => 40*i ) | |
.duration(900) | |
.ease('elastic') | |
.attr("dx", -500) | |
//city | |
d3.selectAll('text.city') | |
.transition() | |
.delay( (d,i) => 40*i ) | |
.duration(900) | |
.ease('elastic') | |
.attr("dx", -500) | |
} | |
//bar cart | |
let barChart = () => { | |
rects | |
.attr("rx", 0 ) | |
.attr("ry", 0 ) | |
.transition() | |
.delay( (d,i) => 20*i ) | |
.duration(900) | |
.ease('elastic')//linear, quad, cubic, sin, exp, circle, elastic, back, bounce | |
.attr("x", (d,i) => 150 ) | |
.attr("y", (d,i) => i * 17 ) | |
.attr("width", (d,i) => d["age"]) | |
.attr("height", (d,i) => 15) | |
.attr("fill", (d, i) => (i < 3 ? "#99c125" : "#394147")) | |
.attr("opacity", 1) | |
.attr("transform", "translate(0,0) rotate(0)") | |
.attr("opacity", (d,i)=> i < 12 ? 1 : 0 )//only show 12 people | |
//age text | |
d3.selectAll('text.age') | |
.transition() | |
.delay( (d,i) => 20*i ) | |
.duration(900) | |
.ease('elastic') | |
//align text right | |
.attr("text-anchor", "start") | |
.attr("dx", 160) | |
.attr("dy", (d,i)=> (i * 17) + 12) | |
.attr("opacity", (d,i)=> i < 12 ? 1 : 0 )//nly show 12 people | |
//city text | |
d3.selectAll('text.city') | |
.transition() | |
.delay( (d,i) => 20*i ) | |
.duration(900) | |
.ease('elastic') | |
//align text left | |
.attr("text-anchor", "end") | |
.attr("dx", 140) | |
.attr("dy", (d,i)=> (i * 17) + 12) | |
.attr("opacity", (d,i)=> i < 12 ? 1 : 0 )//only show 12 people | |
} | |
//waypoints scroll constructor | |
function scroll(n, offset, func1, func2){ | |
return new Waypoint({ | |
element: document.getElementById(n), | |
handler: function(direction) { | |
direction == 'down' ? func1() : func2(); | |
}, | |
//start 75% from the top of the div | |
offset: offset | |
}); | |
}; | |
//triger these functions on page scroll | |
new scroll('div2', '75%', grid2, grid); | |
new scroll('div4', '75%', divide, grid); | |
new scroll('div6', '75%', barChart, divide); | |
//start grid on page load | |
grid(); | |
</script> | |
</body> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment