Built with blockbuilder.org
forked from romsson's block: Stacked bar chart v4
license: mit |
Built with blockbuilder.org
forked from romsson's block: Stacked bar chart v4
<!DOCTYPE html> | |
<html lang="en"> | |
<style> | |
.axis .domain { | |
display: none; | |
} | |
</style> | |
<body> | |
<head> | |
<meta charset="utf-8"> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font- awesome/4.4.0/css/font-awesome.min.css"> | |
</head> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script> | |
var n = 10, // number of samples (columns) | |
m = 5; // number of series (layers) | |
var data = d3.range(n).map(function() { | |
return d3.range(m).map(Math.random); | |
}); | |
var margin = {top: 20, right: 30, bottom: 30, left: 40}, | |
width = 960 - margin.left - margin.right, | |
height = 500 - margin.top - margin.bottom; | |
var layers = d3.stack().keys(d3.range(m))(data); | |
var svg = d3.select("body").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 + ")"); | |
// Display stack bar chart first | |
stackBar() | |
// Button to switch between modes | |
//container for all buttons | |
var allButtons= svg.append("g") | |
.attr("id","allButtons"); | |
//colors for different button states | |
var defaultColor= "#7777BB" | |
var hoverColor= "#0000ff" | |
var pressedColor= "#000077" | |
var labels= ["Grouped", "Stacked"]; | |
//groups for each button (which will hold a rect and text) | |
var buttonGroups= allButtons.selectAll("g.button") | |
.data(labels) | |
.enter() | |
.append("g") | |
.attr("class","button") | |
.style("cursor","pointer") | |
.on("click", buttonClicked) | |
.on("mouseover", function() { | |
if (d3.select(this).select("rect").attr("fill") != pressedColor){ | |
d3.select(this) | |
.select("rect") | |
.attr("fill",hoverColor); | |
} | |
}) | |
.on("mouseout", function() { | |
if (d3.select(this).select("rect").attr("fill") != pressedColor) { | |
d3.select(this) | |
.select("rect") | |
.attr("fill",defaultColor); | |
} | |
}) | |
var bWidth= 80; //button width | |
var bHeight= 30; //button height | |
var bSpace= 10; //space between buttons | |
var x0= 200; //x offset | |
var y0= 66; //y offset | |
//adding a rect to each toggle button group | |
//rx and ry give the rect rounded corner | |
buttonGroups.append("rect") | |
.attr("class","buttonRect") | |
.attr("width",bWidth) | |
.attr("height",bHeight) | |
.attr("x",function(d,i) {return x0+(bWidth+bSpace)*i;}) | |
.attr("y",y0) | |
.attr("rx",5) //rx and ry give the buttons rounded corners | |
.attr("ry",5) | |
.attr("fill",defaultColor) | |
//adding text to each toggle button group, centered | |
//within the toggle button rect | |
buttonGroups.append("text") | |
.attr("class","buttonText") | |
.attr("font-family","FontAwesome") | |
.attr("x",function(d,i) { | |
return x0 + (bWidth+bSpace)*i + bWidth/2; | |
}) | |
.attr("y",y0+bHeight/2) | |
.attr("text-anchor","middle") | |
.attr("dominant-baseline","central") | |
.attr("fill","white") | |
.text(function(d) {return d;}) | |
// update button color when clicked | |
function updateButtonColors(button, parent) { | |
parent.selectAll("rect") | |
.attr("fill",defaultColor) | |
button.select("rect") | |
.attr("fill",pressedColor) | |
} | |
function buttonClicked(type) { | |
updateButtonColors(d3.select(this), d3.select(this.parentNode)) | |
if (type == "Stacked"){ | |
stackBar() | |
} | |
if (type == "Grouped") { | |
groupBar() | |
} | |
} | |
function stackBar(){ | |
var y = d3.scaleLinear() | |
.domain([0, m]) | |
.rangeRound([height, 0]) | |
.nice(); | |
var x = d3.scaleBand() | |
.rangeRound([0, width]) | |
.paddingInner(0.05) | |
.align(0.1) | |
.domain(d3.range(n)); | |
var color = d3.scaleOrdinal() | |
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]); | |
if (d3.select("g").selectAll("g.bar").empty() === true) { | |
d3.select("g").selectAll("g.bar") | |
.data(layers) | |
.enter() | |
.append("g") | |
.attr("class", "bar") | |
.each(function(d) { | |
d3.select(this) | |
.selectAll("rect") | |
.data(d) | |
.enter() | |
.append("rect") | |
.attr("x", function(p, i) { return x(i) }) | |
.attr("y", function(p) { return y(p[1]) }) | |
.attr("height", function(p) { return y(p[0]) - y(p[1]) }) | |
.attr("width", x.bandwidth()) | |
.style("fill", color(d.key)) | |
}) | |
} else { | |
d3.select("g").selectAll("g.bar") | |
.data(layers) | |
.attr("transform", function(_, i) { return "translate(0, 0)" }) | |
.style("fill", function(_, i) { return color(i) }) | |
.each(function(d) { | |
d3.select(this) | |
.selectAll("rect") | |
.data(d) | |
.attr("x", function(p, i) { return x(i) }) | |
.attr("y", function(p) { return y(p[1]) }) | |
.attr("height", function(p) { return y(p[0]) - y(p[1]) }) | |
.attr("width", x.bandwidth()) | |
}) | |
} | |
} | |
function groupBar(){ | |
var y = d3.scaleLinear() | |
.domain([0, m]) | |
.range([height, 0]); | |
var x0 = d3.scaleBand() | |
.domain(d3.range(n)) | |
.range([0, width], .2); | |
var x1 = d3.scaleBand() | |
.domain(d3.range(m)) | |
.range([0, x0.bandwidth() - 10]); | |
var color = d3.scaleOrdinal() | |
.range(["#98abc5", "#8a89a6", "#7b6888", "#6b486b", "#a05d56", "#d0743c", "#ff8c00"]); | |
var layersGroup = [] | |
layers.forEach(function(e) { | |
var tmp = [] | |
e.forEach(function(a, i) { | |
tmp.push(a[1]) | |
}) | |
layersGroup.push(tmp) | |
}) | |
d3.selectAll("g.bar") | |
.data(layersGroup) | |
.attr("transform", function(_, i) { return "translate(" + x1(i) + ",0)" }) | |
.style("fill", function(_, i) { return color(i) }) | |
.each(function(d) { | |
d3.select(this) | |
.selectAll("rect") | |
.data(d) | |
.attr("width", x1.bandwidth()) | |
.attr("height", function(p) { return height - y(p) }) | |
.attr("x", function(_, i) { return x0(i) }) | |
.attr("y", function(p) { return y(p) }) | |
}) | |
} | |
</script> | |
</body> | |
</html> |