Skip to content

Instantly share code, notes, and snippets.

@jowang0319
Created November 2, 2015 16:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jowang0319/c7d9dfa0e8b8f5088107 to your computer and use it in GitHub Desktop.
Save jowang0319/c7d9dfa0e8b8f5088107 to your computer and use it in GitHub Desktop.
Week 10: tooltips
Causes 0-27 days 1-59 months 5-14 years 15-29 years 30-49 years 50-59 years 60-69 years 70+ years
HIV/AIDS 446 44911 43579 108754 313285 43264 13563 4391
Diarrhoealdiseases 4085 147953 45706 22471 23188 10032 14348 29802
Parasiticandvectordiseases 3 228985 25280 14979 14638 6294 5890 10246
Malaria 0 227114 14597 10483 9700 3565 3552 7474
Respiratoryinfections 28787 183134 34728 27111 26234 20657 36572 121805
Lowerrespiratoryinfections 28748 182660 34563 27033 26158 20598 36490 121568
Neonatalconditions 356160 37225 0 0 0 0 0 0
Pretermbirthcomplications 143914 22427 0 0 0 0 0 0
Birthasphyxiaandbirthtrauma 128327 11613 0 0 0 0 0 0
Nutritionaldeficiencies 0 51738 27449 20168 17908 9174 12787 34889
Malignantneoplasms 0 1619 3969 13772 56899 50079 54241 51896
Cardiovasculardiseases 0 5195 9865 16107 42538 57462 100466 281029
Ischaemicheartdisease 0 1130 1444 3550 10596 16696 31175 81729
Stroke 0 0 2930 4805 17727 26003 45748 133261
Digestivediseases 0 6276 11198 12035 20650 17950 24209 41744
Injuries 5108 65640 68832 60400 39524 14880 15151 32537
Unintentionalinjuries 4088 62002 61010 42539 30140 12119 12736 28691
Roadinjury 244 7852 14745 15326 11741 4325 3830 5447
<!DOCTYPE html>
<!-- code loosely inspired by this block https://gist.github.com/mstanaland/6100713 -->
<meta charset="utf-8">
<style>
body {
font: 12px sans-serif;
padding: 50px;
}
#form {
position: relative;
right: 10px;
top: 10px;
padding-bottom: 20px;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.bar {
fill: steelblue;
}
.myTooltip {
position: absolute;
z-index: 10;
}
.myTooltip p {
font-family: 'Roboto', sans-serif;
background-color: rgba(255, 255, 255, .8);
padding: .5em 1em;
font-size: 12px;
line-height: 17px;
color: black;
}
.tooltipHeader {
font-weight: 700;
font-size: 12.5px;
}
svg rect:hover {
opacity: .3;
}
svg circle:hover {
opacity: .3;
}
.unfocused {
stroke-opacity: 25%;
}
.focused {
stroke-width: 2px;
stroke-opacity: 100%;
}
.x.axis path {
display: none;
}
</style>
<body>
<h2>Deaths from Illnesses in 2013 in Selected South African Countries</h2>
<p><a href="http://apps.who.int/gho/data/node.main.ghe100-by-cause?lang=en">WHO data</a>, major cause of death of women in Afica Region by age, year 2012.</p>
<div id="form">
<label><input type="radio" name="mode" value="bycount" checked>Raw Count</label>
<label><input type="radio" name="mode" value="bypercent">Percent of Illness</label>
</div>
<div id="chart"></div>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script>
<script>
var margin = {top: 20, right: 150, bottom: 100, left: 55},
width = 1200 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
var xScale = d3.scale.ordinal()
.rangeRoundBands([0, width], .3);
var yScale = d3.scale.linear()
.rangeRound([height, 0]);
var color = d3.scale.category20();
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.innerTickSize([0]);
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.tickFormat(d3.format(".2s")); // for the stacked totals version
var stack = d3.layout
.stack();
var svg = d3.select("#chart").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 + ")");
d3.csv("data2.csv", function(error, data) {
if (error) {
console.log(error);
}
data.sort(function(a,b) { return a.Causes - b.Causes;});
// how would we sort by largest total bar? what would we have to calculate?
var ageRange = ["0-27 days","1-59 months","5-14 years","15-29 years",
"30-49 years","50-59 years","60-69 years","70+ years"];
dataToStack = makeData(ageRange, data);
console.log(dataToStack);
var stacked = stack(dataToStack);
console.log(stacked);
xScale.domain(data.map(function(d) { return d.Causes; }));
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.attr("dy", ".5em")
.attr("transform", "rotate(-30)")
.style("text-anchor", "end");
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", -margin.left)
.attr("x", -(height-margin.bottom)/2)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Deaths");
var cause = svg.selectAll(".cause")
.data(stacked)
.enter().append("g")
.attr("class", "cause")
.style("fill", function(d, i) { return color(i); });
var rectangles = cause.selectAll("rect")
.data(function(d) {
console.log("array for a rectangle");
return d; }) // this just gets the array for bar segment.
.enter().append("rect")
.attr("width", xScale.rangeBand());
// this just draws them in the default way, now they're appended.
transitionCount();
drawLegend();
var myTooltip = d3.select("body")
.append("div")
.attr("class", "myTooltip");
var percentClicked = false;
d3.selectAll("input").on("change", handleFormClick);
// All the functions for stuff above!
function handleFormClick() {
if (this.value === "bypercent") {
percentClicked = true;
transitionPercent();
} else {
percentClicked = false;
transitionCount();
}
}
function makeData (age,data) {
return ageRange.map(function(age) {
return data.map(function(d) {
return {x: d["Causes"], y: +d[age], ageRange: age};
})
});
}
function transitionPercent() {
yAxis.tickFormat(d3.format("%"));
stack.offset("expand"); // use this to get it to be relative/normalized!
var stacked = stack(makeData(ageRange, data));
// call function to do the bars, which is same across both formats.
transitionRects(stacked);
}
function transitionCount() {
yAxis.tickFormat(d3.format(".2s")); // for the stacked totals version
stack.offset("zero");
var stacked = stack(makeData(ageRange, data));
transitionRects(stacked);
console.log("stacked", stacked);
}
function transitionRects(stacked) {
// this domain is using the last of the stacked arrays, which is the last illness, and getting the max height.
yScale.domain([0, d3.max(stacked[stacked.length-1], function(d) { return d.y0 + d.y; })]);
// attach new fixed data
var cause = svg.selectAll(".cause")
.data(stacked);
// same on the rects
cause.selectAll("rect")
.data(function(d) {
console.log("array for a rectangle");
return d;
}) // this just gets the array for bar segment.
svg.selectAll("g.cause rect")
.transition()
.duration(250)
.attr("x", function(d) {
return xScale(d.x); })
.attr("y", function(d) {
return yScale(d.y0 + d.y); }) //
.attr("height", function(d) {
return yScale(d.y0) - yScale(d.y0 + d.y); }); // height is base - tallness
svg.selectAll(".y.axis").transition().call(yAxis);
}
// Building a legend by hand, based on http://bl.ocks.org/mbostock/3886208
function drawLegend() {
var legend = svg.selectAll(".legend")
.data(color.domain().slice()) // what do you think this does?
.enter().append("g")
.attr("class", "legend")
.attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
legend.append("rect")
.attr("x", width)
.attr("width", 18)
.attr("height", 18)
.style("fill", color);
legend.append("text")
.attr("x", width + 24)
.attr("y", 9)
.attr("dy", ".35em")
.style("text-anchor", "start")
.text(function(d, i) { return ageRange[i]; });
}
rectangles
.on("mouseover", mouseoverFunc)
.on("mousemove", mousemoveFunc)
.on("mouseout", mouseoutFunc);
function mouseoverFunc(d) {
console.log("moused over", d.x);
if(percentClicked) {
myTooltip
.style("display", null)
.html("<p><span class='tooltipHeader'>" + d.x + "</span><br>"+ d.ageRange + ": " + d3.format("%")(d.y) + "</p>");
} else {
console.log("method", d.ageRange, "percent", d.y);
myTooltip
.style("display", null)
.html("<p><span class='tooltipHeader'>" + d.x + "</span><br>"+ d.ageRange + ": " +d.y + "</p>");
}
}
function mousemoveFunc(d) {
myTooltip
.style("top", (d3.event.pageY - 5) + "px")
.style("left", (d3.event.pageX + 10) + "px");
}
function mouseoutFunc(d) {
return myTooltip.style("display", "none"); // this sets it to invisible!
}
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment