Silence is golden
Last active
April 4, 2016 09:30
-
-
Save pirhoo/1a734463cae06cd5ede829e403ee7d41 to your computer and use it in GitHub Desktop.
OSF visualization
This file contains hidden or 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: gpl-3.0 | |
border: no | |
height: 500 |
This file contains hidden or 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
var W = 960, H = 500; | |
var NODE_RADIUS = 10, CLUSTER_PADDING = 15; | |
var GENDER_FILL = { | |
'male': '#036F73', | |
'female': '#EF504F', | |
'other': '#FEF2D8' | |
}; | |
var KEYS_MAP = { | |
"How would you describe yourself?": "gender", | |
"What year were you born in?": "born_year", | |
"Where are you based?": "based_place", | |
"Which one is your favorite?": "favorite", | |
"We will crowdsource the number of power cuts in Douala, Cameroon, using SMS and we will sell the data to corporations thinking of settling in.": "power_cuts_interest", | |
"We will create a database of all payments made by Big Pharma to doctors in the United States, write articles on the topic and sell the resulting tables.": "big_pharma_interest", | |
"We will create an agency that makes infographics for corporations and media outlets.": "agency_interest", | |
"We'll measure dialects in a country and do a web-app that tells people where they're from according to their speaking habits.": "speaking_interest" | |
}; | |
var STEP_COLUMN = { | |
1: 'gender', | |
2: 'born_year', | |
3: 'based_place', | |
4: 'favorite', | |
5: 'power_cuts_interest', | |
6: 'big_pharma_interest', | |
7: 'agency_interest', | |
8: 'speaking_interest' | |
}; | |
var CLUSTERS = { | |
// Gender | |
"female": { x: W * 1/3 - W * 1/6, y: H/2, radius: W/6}, | |
"male": { x: W * 2/3 - W * 1/6, y: H/2, radius: W/6}, | |
"other": { x: W * 3/3 - W * 1/6, y: H/2, radius: W/6}, | |
// Baby animal | |
"cat": { x: W * 1/3 - W * 1/6, y: H/2, radius: W/6}, | |
"pup": { x: W * 2/3 - W * 1/6, y: H/2, radius: W/6}, | |
"prairie dog": { x: W * 3/3 - W * 1/6, y: H/2, radius: W/6}, | |
// Interest | |
"1": { x: W * 1/5 - W * 1/10, y: H/2, radius: W/6}, | |
"2": { x: W * 2/5 - W * 1/10, y: H/2, radius: W/6}, | |
"3": { x: W * 3/5 - W * 1/10, y: H/2, radius: W/6}, | |
"4": { x: W * 4/5 - W * 1/10, y: H/2, radius: W/6}, | |
"5": { x: W * 5/5 - W * 1/10, y: H/2, radius: W/6} | |
}; | |
var HIDDEN_CLUSTER = { | |
x: W/2, | |
y: H * 2, | |
radius: 0 | |
} |
This file contains hidden or 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
# | How would you describe yourself? | What year were you born in? | Where are you based? | Which one is your favorite? | We will crowdsource the number of power cuts in Douala, Cameroon, using SMS and we will sell the data to corporations thinking of settling in. | We will create a database of all payments made by Big Pharma to doctors in the United States, write articles on the topic and sell the resulting tables. | We will create an agency that makes infographics for corporations and media outlets. | We'll measure dialects in a country and do a web-app that tells people where they're from according to their speaking habits. | latitude | longitude | |
---|---|---|---|---|---|---|---|---|---|---|---|
77dda7b22612474e10ac9b3f06ead13d | Female | 1985 | Beijing | Prairie dog | 1 | 1 | 1 | 3 | 39.904211 | 116.407395 | |
baec107d44d5768d63c43a278ea9db58 | Male | 1988 | Lagos | Cat | 4 | 5 | 2 | 4 | 6.524379 | 3.379206 | |
a62630638d155d436d1200e515a7187b | Male | 1990 | Delhi | Cat | 3 | 4 | 2 | 3 | 28.613939 | 77.209021 | |
5e2b572f5b5350091771ed4352bea835 | Other | 1960 | Karachi | Pup | 1 | 1 | 1 | 24.861462 | 67.009939 | ||
66fa48c89077092ad267315ae52b311d | Female | 1955 | Istanbul | Prairie dog | 4 | 3 | 2 | 41.008238 | 28.978359 | ||
93594e1935a5d953df969fe04530d2b5 | Female | 1974 | Tokyo | Cat | 3 | 4 | 2 | 35.689488 | 139.691706 | ||
e84348a4722eb707a361804e8d1964b8 | Female | 1945 | Mumbai | Cat | 1 | 2 | 1 | 19.075984 | 72.877656 | ||
025ca0ea392f1c8b585cde76f9eeeec5 | Male | 1985 | Moscow | Prairie dog | 4 | 1 | 3 | 55.755826 | 37.6173 | ||
08da7e45884adfdb603b37dc1b236cca | Female | 1969 | São Paulo | Pup | 3 | 4 | 4 | -23.55052 | -46.633309 | ||
77dda7b22612474e10ac9b3f06ead13d | Female | 1988 | Shenzhen | Prairie dog | 1 | 1 | 1 | 2 | 22.543096 | 114.057865 | |
baec107d44d5768d63c43a278ea9db58 | Male | 1986 | Seoul | Cat | 4 | 5 | 2 | 1 | 37.566535 | 126.977969 | |
a62630638d155d436d1200e515a7187b | Male | 1990 | Jakarta | Cat | 3 | 4 | 1 | 4 | -6.208763 | 106.845599 | |
5e2b572f5b5350091771ed4352bea835 | Female | 1960 | Guangzhou | Pup | 1 | 2 | 1 | 23.12911 | 113.264385 | ||
66fa48c89077092ad267315ae52b311d | Female | 1945 | Kinshasa | Prairie dog | 4 | 2 | 2 | -4.441931 | 15.266293 | ||
93594e1935a5d953df969fe04530d2b5 | Female | 1979 | Cairo | Cat | 3 | 1 | 3 | 30.04442 | 31.235712 | ||
e84348a4722eb707a361804e8d1964b8 | Female | 1945 | Mexico City | Cat | 1 | 3 | 4 | 19.432608 | -99.133208 | ||
025ca0ea392f1c8b585cde76f9eeeec5 | Male | 1975 | Lima | Prairie dog | 4 | 4 | 2 | -12.046374 | -77.042793 | ||
08da7e45884adfdb603b37dc1b236cca | Female | 1976 | London | Pup | 3 | 2 | 3 | 51.507351 | -0.127758 | ||
025ca0ea392f1c8b585cde76f9eeeec5 | Male | 1956 | New York City | Cat | 1 | 1 | 4 | 40.712784 | -74.005941 |
This file contains hidden or 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
// Move d to be adjacent to the cluster node. | |
function cluster(alpha, nodes) { | |
return function(d) { | |
var cluster = clusters[d.cluster]; | |
if (cluster === d) return; | |
var x = d.x - cluster.x, | |
y = d.y - cluster.y, | |
l = Math.sqrt(x * x + y * y), | |
r = NODE_RADIUS + cluster.radius; | |
if (l != r) { | |
l = (l - r) / l * alpha; | |
d.x -= x *= l; | |
d.y -= y *= l; | |
} | |
}; | |
} | |
// Resolves collisions between d and all other circles. | |
function collide(alpha, nodes) { | |
var padding = 2; | |
var quadtree = d3.geom.quadtree(nodes); | |
return function(d) { | |
var r = 10, | |
nx1 = d.x - r, | |
nx2 = d.x + r, | |
ny1 = d.y - r, | |
ny2 = d.y + r; | |
quadtree.visit(function(quad, x1, y1, x2, y2) { | |
if (quad.point && (quad.point !== d)) { | |
var x = d.x - quad.point.x, | |
y = d.y - quad.point.y, | |
l = Math.sqrt(x * x + y * y), | |
r = NODE_RADIUS + quad.point.radius + (d.cluster === quad.point.cluster ? padding : CLUSTER_PADDING); | |
if (l < r) { | |
l = (l - r) / l * alpha; | |
d.x -= x *= l; | |
d.y -= y *= l; | |
quad.point.x += x; | |
quad.point.y += y; | |
} | |
} | |
return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1; | |
}); | |
}; | |
} |
This file contains hidden or 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> | |
<meta charset="utf-8"> | |
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" media="screen" charset="utf-8"> | |
<link rel="stylesheet" href="./style.css" media="screen" charset="utf-8"> | |
<body> | |
<div class="workspace"> | |
<div class="workspace__legend workspace__legend--1 row text-center"> | |
<div class="col col-xs-4">Male</div> | |
<div class="col col-xs-4">Female</div> | |
<div class="col col-xs-4">Other</div> | |
</div> | |
<div class="workspace__legend workspace__legend--2 row text-center"> | |
<div class="col col-xs-3">1930</div><!-- Years start at 1920 --> | |
<div class="col col-xs-3">1950</div> | |
<div class="col col-xs-3">1970</div> | |
<div class="col col-xs-3">1990</div><!-- Years end at 2000 --> | |
<div class="workspace__legend__axis"></div> | |
</div> | |
<div class="workspace__legend workspace__legend--4 row text-center"> | |
<div class="col col-xs-4"> | |
<img src="//i.imgur.com/anjmG4T.jpg" alt="cat" width="100" class="img-thumbnail img-responsive img-circle" /> | |
</div> | |
<div class="col col-xs-4"> | |
<img src="//i.imgur.com/IinAQ0k.jpg" alt="dog" width="100" class="img-thumbnail img-responsive img-circle" /> | |
</div> | |
<div class="col col-xs-4"> | |
<img src="//i.imgur.com/psHq30V.jpg" alt="prairie dog" width="100" class="img-thumbnail img-responsive img-circle" /> | |
</div> | |
</div> | |
<div class="workspace__legend workspace__legend--interest workspace__legend--5 workspace__legend--6 workspace__legend--7 workspace__legend--8 text-center"> | |
<div class="col"> | |
<img src="//imgur.com/xqBQbQ1.jpg" alt="star" width="20" /> | |
</div> | |
<div class="col"> | |
<img src="//imgur.com/xqBQbQ1.jpg" alt="star" width="20" /> | |
<img src="//imgur.com/xqBQbQ1.jpg" alt="star" width="20" /> | |
</div> | |
<div class="col"> | |
<img src="//imgur.com/xqBQbQ1.jpg" alt="star" width="20" /> | |
<img src="//imgur.com/xqBQbQ1.jpg" alt="star" width="20" /> | |
<img src="//imgur.com/xqBQbQ1.jpg" alt="star" width="20" /> | |
</div> | |
<div class="col"> | |
<img src="//imgur.com/xqBQbQ1.jpg" alt="star" width="20" /> | |
<img src="//imgur.com/xqBQbQ1.jpg" alt="star" width="20" /> | |
<img src="//imgur.com/xqBQbQ1.jpg" alt="star" width="20" /> | |
<img src="//imgur.com/xqBQbQ1.jpg" alt="star" width="20" /> | |
</div> | |
<div class="col"> | |
<img src="//imgur.com/xqBQbQ1.jpg" alt="star" width="20" /> | |
<img src="//imgur.com/xqBQbQ1.jpg" alt="star" width="20" /> | |
<img src="//imgur.com/xqBQbQ1.jpg" alt="star" width="20" /> | |
<img src="//imgur.com/xqBQbQ1.jpg" alt="star" width="20" /> | |
<img src="//imgur.com/xqBQbQ1.jpg" alt="star" width="20" /> | |
</div> | |
</div> | |
<div class="workspace__next workspace__next--0"> | |
<a class="btn btn-default">See the result of the poll</a> | |
</div> | |
<div class="workspace__next workspace__next--1"> | |
<h3>What is your gender?</h3> | |
<a class="btn btn-default">Continue</a> | |
</div> | |
<div class="workspace__next workspace__next--2"> | |
<h3>What year were you born in?</h3> | |
<a class="btn btn-default">Continue</a> | |
</div> | |
<div class="workspace__next workspace__next--3"> | |
<h3>Where are you based?</h3> | |
<a class="btn btn-default">Continue</a> | |
</div> | |
<div class="workspace__next workspace__next--4"> | |
<h3>Which one is your favorite?</h3> | |
<a class="btn btn-default">Continue</a> | |
</div> | |
<div class="workspace__next workspace__next--5"> | |
<h3>We will crowdsource the number of power cuts in Douala, Cameroon, using SMS and we will sell the data to corporations thinking of settling in.</h3> | |
<a class="btn btn-default">Continue</a> | |
</div> | |
<div class="workspace__next workspace__next--6"> | |
<h3>We will create a database of all payments made by Big Pharma to doctors in the United States, write articles on the topic and sell the resulting tables.</h3> | |
<a class="btn btn-default">Continue</a> | |
</div> | |
<div class="workspace__next workspace__next--7"> | |
<h3>We will create an agency that makes infographics for corporations and media outlets.</h3> | |
<a class="btn btn-default">Continue</a> | |
</div> | |
<div class="workspace__next workspace__next--8"> | |
<h3>We'll measure dialects in a country and do a web-app that tells people where they're from according to their speaking habits.</h3> | |
<a class="btn btn-default">Replay !</a> | |
</div> | |
</div> | |
</body> | |
<script src="//d3js.org/d3.v3.min.js"></script> | |
<script src="//d3js.org/d3.geo.projection.v0.min.js"></script> | |
<script src="//d3js.org/topojson.v1.min.js"></script> | |
<script src="./constants.js"></script> | |
<script src="./force.js"></script> | |
<script> | |
// Creates SVG | |
var svg = d3.select(".workspace").append("svg").attr("width", W).attr("height", H); | |
var force = d3.layout.force(); | |
var people = null; | |
var yearClusters = []; | |
// Create a cluster for every year | |
d3.range(80).forEach(function(y) { | |
var year = 1920 + y; | |
yearClusters[year] = { | |
radius: 10, | |
x: (20 + y) * W/100, | |
y: H/2 | |
}; | |
}) | |
// Map conf | |
var map = { | |
projection: d3.geo.naturalEarth().scale(200).translate([W/2, H/1.8]).precision(.1), | |
path: d3.geo.path(), | |
g: svg.append("g").attr("class", "world") | |
}; | |
function randomFunc(start, end){ | |
return function() { | |
return start + Math.random() * (end - start); | |
} | |
} | |
function init(data){ | |
// We have to edit the data | |
data.forEach(function(d) { | |
d.x = randomFunc(10, W - 10)(); | |
d.y = randomFunc(10, H - 10)(); | |
d.radius = 10; | |
// We map column names | |
Object.keys(d).forEach(function(key) { | |
if(KEYS_MAP.hasOwnProperty(key)) { | |
// Copy mapped key and cast numeric values | |
d[ KEYS_MAP[key] ] = isNaN(d[key]) ? d[key].toLowerCase() : 1*d[key]; | |
delete d[key]; | |
} | |
}); | |
}); | |
// Create peoples shapes | |
people = svg.selectAll('.people') | |
.data(data).enter() | |
.append('circle') | |
.attr('class', 'people') | |
.attr('cx', function(d) { return W/2 }) | |
.attr('cy', function(d) { return H/2 }) | |
.style('fill', function(d) { return GENDER_FILL[d.gender]; }) | |
.style('stroke', function(d) { return d3.rgb(GENDER_FILL[d.gender]).darker(1); }) | |
.attr('r', 0); | |
// Prepare force layout | |
force.nodes(data) | |
.friction(.2) | |
.size([W, H]) | |
.on("tick", function(e) { | |
// Push different nodes in different directions for clustering. | |
data.forEach(function(d, i) { | |
d.y += (d.cluster.y - d.y) * e.alpha; | |
d.x += (d.cluster.x - d.x) * e.alpha; | |
}); | |
people.each(collide(.1, data)) | |
.attr("cx", function(d) { return d.x; }) | |
.attr("cy", function(d) { return d.y; }); | |
}); | |
// Setup step 0 | |
stepFunc(0, data)(); | |
// Bind click event on the start button | |
for(var i = 0; i <= 8; i++) { | |
var next = (i % 8) + 1; | |
d3.select(".workspace__next--" + i + " .btn").on("click", stepFunc(next, data)); | |
} | |
} | |
function createMap(error, world) { | |
if(error) throw error; | |
map.path.projection(map.projection); | |
map.g.append("path") | |
.datum(topojson.merge(world, world.objects.countries.geometries)) | |
.attr("class", "world__land") | |
.attr("d", map.path); | |
} | |
function stepFunc(n, data) { | |
return function() { | |
// Change body class to the current step | |
d3.select('body').attr('class', 'step--' + n); | |
// Activate the right button | |
d3.selectAll('.workspace__next').classed('workspace__next--active', false); | |
d3.select('.workspace__next--' + n).classed('workspace__next--active', true); | |
// Activate the right legend | |
d3.selectAll('.workspace__legend').classed('workspace__legend--active', false); | |
d3.select('.workspace__legend--' + n).classed('workspace__legend--active', true); | |
// Trigger a different function according to the step | |
switch(n) { | |
case 0: | |
// Animate appearance | |
people.transition() | |
.delay(function(d, i) { return i * 150 }) | |
.attr('cx', function(d) { return d.x }) | |
.attr('cy', function(d) { return d.y }) | |
.attr('r', function(d, i) { return d.radius }); | |
break; | |
case 2: | |
// Ensure every element is visible | |
people.transition().attr('r', function(d, i) { return d.radius = 5 }); | |
// Change the cluster attribute to use the gender | |
data.forEach(function(d) { d.cluster = yearClusters[d.born_year]; }); | |
// Start layout | |
force.start(); | |
break; | |
case 3: | |
// Ensure every element is visible | |
people.transition().attr('r', function(d, i) { return d.radius = 5 }); | |
// Change the cluster attribute to use the gender | |
data.forEach(function(d) { | |
d.cluster = { | |
radius: 0, | |
x: map.projection([d.longitude, d.latitude])[0], | |
y: map.projection([d.longitude, d.latitude])[1] | |
} | |
}); | |
// Start layout | |
force.start(); | |
break; | |
default: | |
// Ensure every element is visible | |
people.transition().attr('r', function(d, i) { return d.radius = 10 }); | |
// Change the cluster attribute to use the gender | |
data.forEach(function(d) { | |
// Each step use a different column | |
d.cluster = CLUSTERS[ d[ STEP_COLUMN[n] ] ] || HIDDEN_CLUSTER; | |
}); | |
// Start layout | |
force.start(); | |
break; | |
} | |
} | |
} | |
d3.csv("data.csv", init); | |
d3.json("world-50m.json", createMap); | |
</script> |
This file contains hidden or 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
.workspace { | |
width: 960px; | |
height:500px; | |
position: relative; | |
background:#fafafa; | |
overflow: hidden; | |
margin:auto; | |
box-shadow: 0 0 1px 2px #DCD2C7; | |
position: fixed; | |
top:50%; | |
left:50%; | |
margin-left: -480px; | |
margin-top: -250px; | |
} | |
@media(max-height:500px) { | |
.workspace { | |
position: static; | |
margin:0; | |
} | |
} | |
.workspace__next { | |
position:absolute; | |
bottom:20px; | |
left:20px; | |
right:20px; | |
text-align: right; | |
display: inline-block; | |
transition: 500ms; | |
opacity:0; | |
pointer-events: none; | |
min-height:34px; | |
z-index:20; | |
} | |
.workspace__next.workspace__next--active { | |
opacity:1; | |
pointer-events: all; | |
} | |
.workspace__next h3 { | |
font-weight:100; | |
font-size:1.2em; | |
position: absolute; | |
bottom:50%; | |
left:0; | |
right:0; | |
transform: translate(0, 50%); | |
padding:0 150px; | |
margin:0; | |
text-align: center; | |
pointer-events: none; | |
} | |
.workspace__next .btn { | |
border-width:3px; | |
border-color:#CCC2B8; | |
position: relative; | |
overflow: visible; | |
color:#BE1525; | |
background:#DCD2C7; | |
font-weight: bold; | |
} | |
.workspace__legend { | |
position: absolute; | |
top:0; | |
bottom:0; | |
left:0; | |
right:0; | |
opacity:0; | |
color:#CCC2B8; | |
pointer-events: none; | |
z-index:1; | |
transition: opacity 500ms; | |
} | |
.workspace__legend--active { | |
opacity:1; | |
} | |
.workspace__legend .col { | |
height:100%; | |
padding-top:20px; | |
} | |
.workspace__legend .col:nth-child(odd) { | |
background:#f0f0f0; | |
} | |
.workspace__legend--2 .workspace__legend__axis { | |
position: absolute; | |
top:50%; | |
left:0; | |
right:0; | |
height:1px; | |
background:#CCC2B8; | |
opacity:.2; | |
} | |
.workspace__legend--4 img { | |
border:0; | |
background:#CCC2B8; | |
} | |
.workspace__legend--interest { | |
white-space: nowrap; | |
} | |
.workspace__legend--interest .col { | |
width:20%; | |
display: inline-block; | |
margin:0; | |
} | |
.workspace__legend--interest .col img { | |
opacity:.7; | |
} | |
.people { | |
stroke-width:1.5; | |
} | |
svg { | |
position: relative; | |
z-index:10; | |
} | |
.world { | |
opacity:0; | |
transition: 500ms; | |
} | |
.world .world__land { | |
fill: #ddd; | |
} | |
.step--3 .world { | |
opacity:1; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment