Last active
July 29, 2016 19:51
-
-
Save DimsumPanda/e01126f967d18a8f220deeda44742abb to your computer and use it in GitHub Desktop.
stackedBarcharts
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
var margin = {top: 20, right: 150, bottom: 50, left: 40}, | |
width = 980 - margin.left - margin.right, | |
height = 500 - 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(); // default view is "zero" for the count display. | |
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 + ")"); | |
var tooltip = d3.select("body") | |
.append("div") | |
.attr("class", "tooltip"); | |
var percentClicked = false; | |
d3.csv("segments_table.csv", function(error, data) { | |
if (error) { | |
console.log(error); | |
} | |
console.log(data); | |
data.sort(function(a,b) { return +a.F_lessthan25 - +b.F_lessthan25;}); | |
var segment = ["Asian","Black","Hispanic", "White"]; | |
console.log("segmentcomponents",segment); | |
var stacked = stack(makeData(segment, data)); // needed for default view | |
console.log(stacked); | |
xScale.domain(data.map(function(d) { return d.ethnicity; })); | |
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", 6) | |
.attr("dy", ".71em") | |
.style("text-anchor", "end") | |
.text("segment"); | |
var ethnicity = svg.selectAll(".ethnicity") | |
.data(stacked) | |
.enter().append("g") | |
.attr("class", "ethnicity") | |
.style("fill", function(d, i) { return color(i); }); | |
var rectangles = ethnicity.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(); | |
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(segment, data) { | |
return segment.map(function(component) { | |
return data.map(function(d) { | |
return {x: d["ethnicity"], y: +d[component], component: component}; | |
}) | |
}); | |
} | |
function transitionPercent() { | |
yAxis.tickFormat(d3.format("%")); | |
stack.offset("expand"); // use this to get it to be relative/normalized! | |
var stacked = stack(makeData(segment, 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(segment, data)); | |
transitionRects(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 ethnicity = svg.selectAll(".ethnicity") | |
.data(stacked); | |
// same on the rects | |
ethnicity.selectAll("rect") | |
.data(function(d) { | |
console.log("array for a rectangle"); | |
return d; | |
}) // this just gets the array for bar segment. | |
svg.selectAll("g.ethnicity 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," + Math.abs((i-5) * 20) + ")"; }); | |
// Added the absolute value and transition. I reversed the names, so that I can continue to use category20(), but have health as green to make it stand out. | |
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 segment[i]; }); | |
} | |
// ================================================================ | |
// Mouse Events | |
// ================================================================ | |
rectangles | |
.on("mouseover", mouseoverFunc) | |
.on("mousemove", mousemoveFunc) | |
.on("mouseout", mouseoutFunc); | |
function mouseoverFunc(d) { | |
console.log("moused over", d.x); | |
if(percentClicked) { | |
tooltip | |
.style("display", null) | |
.html("<p><span class='tooltipHeader'>" + d.x + "</span><br>"+ d.component + ": " + d3.format("%")(d.y) + "</p>"); | |
} else { | |
console.log("segment", d.component, "percent", d.y); | |
tooltip | |
.style("display", null) | |
.html("<p><span class='tooltipHeader'>" + d.x + "</span><br>"+ d.component + ": " +d.y + "%</p>"); | |
} | |
} | |
}); |
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> | |
<link href="style.css" rel="stylesheet"></link> | |
</head> | |
<body> | |
<div id="chart"></div> | |
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js"></script> | |
<script src="d3-function.js"></script> | |
</body> | |
</html> |
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
ethnicity | F_lessthan25 | F_greaterthan75 | F_25-50 | F_50-75 | M_lessthan25 | Mgreaterthan75 | M_25-50 | M_50-75 | |
---|---|---|---|---|---|---|---|---|---|
Asian | 327 | 296 | 332 | 309 | 306 | 330 | 307 | 323 | |
Black | 294 | 302 | 330 | 305 | 295 | 363 | 322 | 292 | |
Hispanic | 315 | 351 | 307 | 323 | 312 | 324 | 297 | 306 | |
White | 311 | 298 | 303 | 306 | 308 | 286 | 282 | 338 |
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
body { | |
font: 12px sans-serif; | |
padding: 50px; | |
} | |
svg { | |
background-color: rgb(255, 255, 255); | |
} | |
svg rect:hover { | |
opacity: .3; | |
} | |
svg circle: hover { | |
opacity: .3; | |
} | |
svg g { | |
fill: #ACACAC; | |
} | |
svg g text.label, | |
svg g text.ylabel { | |
fill: #2A2A2A; | |
} | |
svg { | |
background-color: #fff; | |
} | |
#form { | |
position: relative; | |
right: 10px; | |
top: 10px; | |
padding-bottom: 20px; | |
} | |
.axis path, | |
.axis line { | |
fill: none; | |
stroke: #000; | |
shape-rendering: crispEdges; | |
} | |
.line { | |
stroke: #FF9900; | |
fill: none; | |
stroke-opacity: 25%; | |
stroke-width: 1px; | |
} | |
.unfocused { | |
stroke-opacity: 25%; | |
} | |
.focused { | |
stroke-width: 2px; | |
stroke-opacity: 100%; | |
} | |
.bar { | |
fill: steelblue; | |
} | |
.x.axis path { | |
display: none; | |
} | |
.tooltip { | |
position: absolute; | |
z-index: 10; | |
} | |
.tooltip p { | |
background-color: rgba(255,255,255,1); | |
padding: .5em 1em; | |
font-size: 12px; | |
line-height: 17px; | |
color: black; | |
} | |
.tooltipHeader { | |
font-weight: 700; | |
font-size: 12.5px; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment