Built with blockbuilder.org
Last active
July 31, 2019 17:52
-
-
Save jrzief/b4626d5bd41b338279b175ddae3a5cd8 to your computer and use it in GitHub Desktop.
Health and Wealth with tooltip
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: mit |
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> | |
<head> | |
<meta charset="utf-8"> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.9.1/d3-tip.min.js"></script> | |
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> | |
<!-- Latest compiled and minified CSS --> | |
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css"> | |
<!-- Latest compiled and minified JavaScript --> | |
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script> | |
<style> | |
#chart-area svg { | |
margin-left: auto; | |
margin-right: auto; | |
display: block; | |
} | |
#reset-button, #play-button { | |
float: left; | |
margin-right:10px; | |
} | |
#reset-button, #play-button { | |
margin-top: 5px; | |
margin-bottom:10px; | |
} | |
</style> | |
</head> | |
<body> | |
<div class="container"> | |
<div class="row"> | |
<div class="col-md-6"> | |
<button id="play-button" class="btn btn-primary">Play</button> | |
<button id="reset-button" class="btn btn-primary">Reset</button> | |
</div> | |
</div> | |
<div class="row"> | |
<div class="col-md-12"> | |
<div id="chart-area"></div> | |
</div> | |
</div> | |
</div> | |
<script> | |
var margin = { left:80, right:20, top:50, bottom:100 }; | |
var height = 600 - margin.top - margin.bottom, | |
width = 900 - margin.left - margin.right; | |
var g = d3.select("#chart-area") | |
.append("svg") | |
.attr("width", width + margin.left + margin.right) | |
.attr("height", height + margin.top + margin.bottom) | |
.append("g") | |
.attr("transform", "translate(" + margin.left + | |
", " + margin.top + ")"); | |
var time = 0; | |
// Tooltip | |
var tip = d3.tip().attr('class', 'd3-tip') | |
.html(function(d) { | |
var text = "<strong>Country:</strong> <span style='color:red'>" + d.country + "</span><br>"; | |
text += "<strong>Continent:</strong> <span style='color:red;text-transform:capitalize'>" + d.continent + "</span><br>"; | |
text += "<strong>Life Expectancy:</strong> <span style='color:red'>" + d3.format(".2f")(d.life_exp) + "</span><br>"; | |
text += "<strong>GDP Per Capita:</strong> <span style='color:red'>" + d3.format("$,.0f")(d.income) + "</span><br>"; | |
text += "<strong>Population:</strong> <span style='color:red'>" + d3.format(",.0f")(d.population) + "</span><br>"; | |
return text; | |
}); | |
g.call(tip); | |
var interval; | |
var formattedData; | |
//Labels | |
var xLabel = g.append("text") | |
.attr("y", height + 50) | |
.attr("x", width / 2) | |
.attr("font-size", "20px") | |
.attr("text-anchor", "middle") | |
.text("GDP Per Capita ($)"); | |
var yLabel = g.append("text") | |
.attr("transform", "rotate(-90)") | |
.attr("y", -40) | |
.attr("x", -170) | |
.attr("font-size", "20px") | |
.attr("text-anchor", "middle") | |
.text("Life Expectancy (Years)") | |
var timeLabel = g.append("text") | |
.attr("y", height -10) | |
.attr("x", width - 40) | |
.attr("font-size", "40px") | |
.attr("opacity", "0.4") | |
.attr("text-anchor", "middle") | |
.text("1800"); | |
//Scales | |
var x = d3.scaleLog() | |
.base(10) | |
.domain([142, 150000]) | |
.range([0, width]); | |
var y = d3.scaleLinear() | |
.domain([0, 90]) | |
.range([height, 0]); | |
var area = d3.scaleLinear() | |
.range([25*Math.PI, 1500*Math.PI]) | |
.domain([2000, 1400000000]); | |
// X Axis | |
var xAxisCall = d3.axisBottom(x) | |
.tickValues([400, 4000, 40000]) | |
.tickFormat(d3.format("$")); | |
g.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0," + height +")") | |
.call(xAxisCall); | |
// Y Axis | |
var yAxisCall = d3.axisLeft(y) | |
.tickFormat(function(d){ return +d; }); | |
g.append("g") | |
.attr("class", "y axis") | |
.call(yAxisCall); | |
var continentColor = d3.scaleOrdinal(d3.schemeCategory20); | |
//Building the Legend | |
var continents = ["europe", "asia", "americas", "africa"]; | |
var legend = g.append("g") | |
.attr("transform", "translate(" + (width - 10) + | |
"," + (height - 125) + ")"); | |
continents.forEach(function(continent, i){ | |
var legendRow = legend.append("g") | |
.attr("transform", "translate(0, " + (i * 20) + ")"); | |
legendRow.append("rect") | |
.attr("width", 10) | |
.attr("height", 10) | |
.attr("fill", continentColor(continent)); | |
legendRow.append("text") | |
.attr("x", -10) | |
.attr("y", 10) | |
.attr("text-anchor", "end") | |
.style("text-transform", "capitalize") | |
.text(continent); | |
}); | |
//GET THE DATA | |
d3.json("data.json", function(data){ | |
console.log(data); | |
// Clean data | |
formattedData = data.map(function(year){ | |
return year["countries"].filter(function(country){ | |
var dataExists = (country.income && country.life_exp); | |
return dataExists | |
}).map(function(country){ | |
country.income = +country.income; | |
country.life_exp = +country.life_exp; | |
return country; | |
}) | |
}); | |
// First run of the visualization | |
update(formattedData[0]); | |
}); | |
$("#play-button") | |
.on("click", function(){ | |
var button = $(this); | |
if (button.text() == "Play"){ | |
button.text("Pause"); | |
interval = setInterval(step, 100); | |
} | |
else { | |
button.text("Play"); | |
clearInterval(interval); | |
} | |
}) | |
$("#reset-button") | |
.on("click", function(){ | |
time = 0; | |
update(formattedData[0]); | |
}) | |
function step(){ | |
// At the end of our data, loop back | |
time = (time < 167) ? time+1 : 0 | |
update(formattedData[time]); | |
} | |
function update(data) { | |
var t = d3.transition() | |
.duration(100); | |
// JOIN new data with old elements. | |
var circles = g.selectAll("circle") | |
.data(data, function(d) {return d.country; }); | |
// EXIT old elements not present in new data. | |
circles.exit() | |
.attr("class", "exit") | |
.remove(); | |
// ENTER new elements present in new data. | |
var enter = circles.enter() | |
.append("circle") | |
//.filter(function(year) {return year === "1800"}) | |
.attr("class", "enter") | |
.attr("fill", function(d) { return continentColor(d.continent); }) | |
.on("mouseover", tip.show) | |
.on("mouseout", tip.hide) | |
.merge(circles) | |
.transition(t) | |
.attr("cy", function(d){ return y(d.life_exp); }) | |
.attr("cx", function(d){ return x(d.income) }) | |
.attr("r", function(d){ return Math.sqrt(area(d.population) / Math.PI) }); | |
// Update the time label | |
timeLabel.text(+(time + 1850)) | |
} | |
</script> | |
</body> | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment