-
-
Save ramnathv/e8a559ff2f9ab7cd2a7e to your computer and use it in GitHub Desktop.
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> | |
<html> | |
<head> | |
<title>Large Multiples</title> | |
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> | |
<style> | |
rect { | |
fill: #ddd; | |
stroke: none; | |
} | |
rect.active, circle.unit, circle.worker { | |
fill: steelblue; | |
} | |
text { | |
font-family: Helvetica, Arial, sans-serif; | |
fill: lightgray; | |
} | |
text.barlabel { | |
fill: white; | |
pointer-events: none; | |
} | |
text.label, #sentence, .activestep { | |
fill: darkgray; | |
} | |
.step:hover { | |
fill: #ccc; | |
} | |
h1 { | |
font-family: Helvetica, Arial, sans-serif; | |
margin-bottom: 0px; | |
margin-left: 5px; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>It pays to be a CEO in the U.S.</h1> | |
<div id="chart"> | |
</div> | |
<script> | |
var data = [ | |
{country: "Poland", multiple: 28, article: ""}, | |
{country: "Austria", multiple: 36, article: ""}, | |
{country: "Denmark", multiple: 48, article: ""}, | |
{country: "Portugal", multiple: 53, article: ""}, | |
{country: "Norway", multiple: 58, article: ""}, | |
{country: "Japan", multiple: 67, article: ""}, | |
{country: "Israel", multiple: 76, article: ""}, | |
{country: "United Kingdom", multiple: 84, article: "the "}, | |
{country: "Sweden", multiple: 89, article: ""}, | |
{country: "Australia", multiple: 93, article: ""}, | |
{country: "France", multiple: 104, article: ""}, | |
{country: "Czech Republic", multiple: 110, article: "the "}, | |
{country: "Spain", multiple: 127, article: ""}, | |
{country: "Germany", multiple: 147, article: ""}, | |
{country: "Switzerland", multiple: 148, article: ""}, | |
{country: "United States", multiple: 354, article: "the "} | |
]; | |
var intervalID = -1; | |
var TIMEOUT = 20; | |
function makeSquares(numUnits) { | |
svg.selectAll('.unit').remove(); | |
var a = Math.floor(Math.sqrt(numUnits)) // numUnits/.75 for 4:3 ratio of units | |
var b = Math.floor(numUnits/a); | |
var rest = numUnits-a*b; | |
if (rest > a) { | |
a += 1; | |
rest = numUnits-a*b; | |
} | |
if (b > a) { | |
var temp = a; | |
a = b; | |
b = temp; | |
} | |
var circles = []; | |
for (var y = 0; y < b; y += 1) { | |
for (var x = 0; x < a; x += 1) { | |
var c = svg.append('circle') | |
.attr('cx', unitsOffset+x*(unitsize+unitpadding)) | |
.attr('cy', unitsHeight-y*(unitsize+unitpadding)) | |
.attr('r', unitsize/2) | |
.style('visibility', 'hidden') | |
.attr('class', 'unit'); | |
circles.push(c); | |
} | |
} | |
for (var x = 0; x < rest; x += 1) { | |
var c = svg.append('circle') | |
.attr('cx', unitsOffset+x*(unitsize+unitpadding)) | |
.attr('cy', unitsHeight-b*(unitsize+unitpadding)) | |
.attr('r', unitsize/2) | |
.style('visibility', 'hidden') | |
.attr('class', 'unit'); | |
circles.push(c); | |
} | |
svg.select('#ceolabel').transition().attr('y', unitsHeight-b*(unitsize+unitpadding)-16); | |
if (intervalID != -1) { | |
window.clearInterval(intervalID); | |
} | |
var circleIndex = 0; | |
intervalID = window.setInterval(function() { | |
circles[circleIndex].style('visibility', 'visible'); | |
circleIndex += 1; | |
if (circleIndex == circles.length) { | |
window.clearInterval(intervalID); | |
intervalID = -1; | |
} | |
}, TIMEOUT); | |
} | |
var svg = d3.select('#chart').append('svg').attr('width', 694).attr('height', 470); | |
var barheight = 24; | |
var barpad = 3; | |
var unitsize = 17; | |
var unitpadding = 3; | |
var topOffset = 30; | |
var unitsOffset = 320; | |
var unitsHeight = topOffset+16*barheight+15*barpad-unitsize/2; | |
var selected = data[0]; | |
function select(d) { | |
svg.selectAll('.'+selected.country.replace(' ', '-')).classed('active', false); | |
svg.select('.barlabel.'+selected.country.replace(' ', '-')).text(selected.country); | |
svg.selectAll('.'+d.country.replace(' ', '-')).classed('active', true); | |
makeSquares(d.multiple); | |
svg.select('.barlabel.'+d.country.replace(' ', '-')).text(d.country+': '+d.multiple+'x'); | |
svg.select('#sentence').text('In '+d.article+d.country+', the average CEO makes '+d.multiple+' times the salary of the average worker.') | |
selected = d; | |
svg.select('.activestep').classed('activestep', false); | |
activeStep = -1; | |
for (var i = 0; i < steps.length; i++) { | |
if (data[steps[i]] == d) { | |
svg.select('.step-'+i).classed('activestep', true); | |
activeStep = i; | |
} | |
} | |
} | |
svg.selectAll('.bar').data(data).enter() | |
.append('rect') | |
.attr('width', 170) | |
.attr('height', barheight) | |
.attr('x', 5) | |
.attr('y', function(d, i) { return topOffset+i*(barheight+barpad); }) | |
.attr('class', function(d) { return 'bar '+d.country.replace(' ', '-'); }) | |
.on('mouseenter', function(d) { | |
select(d); | |
}); | |
svg.selectAll('.barlabel').data(data).enter() | |
.append('text') | |
.attr('x', barpad*2) | |
.attr('y', function(d, i) { return topOffset+i*(barheight+barpad)+barheight-barpad-4; }) | |
.attr('class', function(d) { return 'barlabel '+d.country.replace(' ', '-'); }) | |
.text(function(d) { return d.country; }); | |
svg.append('circle') | |
.attr('class', 'worker') | |
.attr('cx', unitsOffset-4*(unitsize+unitpadding)) | |
.attr('cy', unitsHeight) | |
.attr('r', unitsize/2); | |
svg.append('text') | |
.attr('class', 'label') | |
.attr('x', unitsOffset-4*(unitsize+unitpadding)-unitsize/2) | |
.attr('y', unitsHeight-16) | |
.text('Worker'); | |
svg.append('text') | |
.attr('class', 'label') | |
.attr('x', unitsOffset-unitsize/2) | |
.attr('y', unitsHeight-16) | |
.attr('id', 'ceolabel') | |
.text('CEO'); | |
svg.append('text') | |
.attr('id', 'sentence') | |
.attr('x', 5) | |
.attr('y', 18); | |
var steps = [0, 3, 7, 13, 15]; | |
var activeStep = 0; | |
var stepsLeft = 493; | |
svg.selectAll('.step').data(steps).enter() | |
.append('rect') | |
.attr('class', function(d, i) { return 'step step-'+i+(i==0?' activestep':''); }) | |
.attr('x', function(d, i) { return stepsLeft+i*(barheight+barpad); }) | |
.attr('y', topOffset) | |
.attr('width', barheight) | |
.attr('height', barheight) | |
.on('click', function(d, i) { | |
svg.select('.activestep').classed('activestep', false); | |
svg.select('.step-'+i).classed('activestep', true); | |
activeStep = i; | |
select(data[d]); | |
}); | |
svg.selectAll('.steplabel').data(steps).enter() | |
.append('text') | |
.attr('class', 'barlabel') | |
.attr('x', function(d, i) { return stepsLeft+7+i*(barheight+barpad); }) | |
.attr('y', topOffset+17) | |
.text(function(d, i) { return ''+(i+1); }); | |
svg.append('rect') | |
.attr('class', 'step') | |
.attr('x', stepsLeft+steps.length*(barheight+barpad)) | |
.attr('y', topOffset) | |
.attr('width', barheight*2.5) | |
.attr('height', barheight) | |
.on('click', function() { | |
if (activeStep < steps.length-1) { | |
svg.select('.activestep').classed('activestep', false); | |
activeStep += 1; | |
svg.select('.step-'+activeStep).classed('activestep', true); | |
select(data[steps[activeStep]]); | |
} | |
}); | |
svg.append('text') | |
.attr('class', 'barlabel') | |
.attr('x', stepsLeft+7+steps.length*(barheight+barpad)) | |
.attr('y', topOffset+17) | |
.text('Next >'); | |
select(data[0]); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment