forked from jadiehm's block: Horizontal bar chart with button scale transition
xxxxxxxxxx
<html lang='en-GB'>
<head></head>
<style>
p {
font-family: sans-serif;
font-size: 14px;
}
/*template styles*/
.gia-chart-wrapper {
max-width: 620px;
margin: 0 auto;
}
/*chart styles*/
.x.axis line {
fill: none;
stroke: #dcdcdc;
stroke-dasharray: 1px 1px;
shape-rendering: crispEdges;
stroke-width: 1px;
}
.y.axis line {
display: none;
}
.tick.g-baseline line {
display: none;
}
.x.axis text {
font-family: sans-serif;
text-anchor: middle !important;
font-size: 12px;
pointer-events: none;
fill: #bdbdbd;
}
.y.axis text {
display: none;
}
.g-axis-text {
font-family: sans-serif;
text-anchor: start !important;
font-size:13px;
fill: #333333;
font-weight: 700;
}
.domain {
display: none;
}
.bar-positive {
fill: #dcdcdc;
}
.bar-negative {
fill: #d61d00;
}
.g-labels {
font-family: sans-serif;
font-size: 14px;
fill: #767676;
text-anchor: start !important;
}
button {
background-color: #ffffff;
border: 1px solid #dcdcdc;
border-radius: 15px;
color: #333333;
padding: 5px 8px;
cursor: pointer;
display: inline-block;
margin-right: 10px;
text-align: center;
text-decoration: none;
font-size: 12px;
line-height: 20px;
font-family: sans-serif;
}
button:focus {
outline: 0;
}
.active {
background-color: #333333;
color: #ffffff;
border: 1px solid #333333;
}
.gia-key {
margin-bottom: 15px;
}
</style>
<body>
<main>
<div class='gia-chart-wrapper'>
<div class='gia-key'></div>
<div class='gia-chart'></div>
</div>
</main>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js" charset="utf-8"></script>
<script>
//Margin conventions
var margin = {top: 0, right: 6, bottom:30, left: 170};
var widther = d3.select(".gia-chart").node().clientWidth;
var width = widther - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
//Appends the svg to the chart-container div
var svg = d3.select(".gia-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 + ")");
//Format comma
var format = d3.format("0,000")
//Creates the xScale
var xScale = d3.scale.linear()
.range([0,width]);
//Creates the yScale
var y0 = d3.scale.ordinal()
.rangeRoundBands([height, 0], 0.1);
//Defines the y axis styles
var yAxis = d3.svg.axis()
.scale(y0)
.tickSize(-width)
.tickPadding(6)
.ticks(4)
.orient("left");
//Defines the y axis styles
var xAxis = d3.svg.axis()
.scale(xScale)
.tickSize(-height)
.tickPadding(6)
.orient("bottom")
.ticks(6);
//Loads the data
d3.csv("budget.csv", ready);
function ready(err, data) {
if (err) throw "error loading data";
//FORMAT data
data.forEach(function(d) {
d.amount = +d.amount;
d.percentChange = +d.percentChange;
d.dollarChange = +d.dollarChange;
});
//Sets the max for the xScale
var maxX = d3.max(data, function(d) { return d.amount; });
var minX = d3.min(data, function(d) { return d.amount; });
//Filters the data
initialType = data.filter(function(d) { return d.type === "Billions of $";});
//Defines the domains
xScale.domain(d3.extent(initialType, function(d) { return d.amount; })).nice();
y0.domain(data.map(function(d) { return d.agency; }));
//Organizes buttons data
var types = data.map(function(d) { return d.type;});
var uniq = d3.set(types).values();
//Buttons
var button = d3.select(".gia-key").selectAll("button")
.data(uniq)
.enter()
.append("button")
.attr("class", function (d) {
if ( d === "Billions of $" ) { return 'active'; }
else { return 'not-active'; }
})
.text(function(d) {return d;})
.on("click", function(d) {
updateChartForType(d);
d3.select(".active").classed("active", false);
d3.select(this).classed("active", true);
});
var xAxisGroup = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
xAxisGroup
.selectAll("g")
.classed("g-baseline", function(d) {return d == 0});
var yAxisGroup = svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + xScale(0) + ",0)")
.call(yAxis);
var bars = svg.selectAll(".bar")
.data(initialType)
.enter().append("rect")
.attr("class", function(d) { return "bar-" + (d.amount < 0 ? "negative" : "positive"); })
.attr("x", function(d) { return xScale(Math.min(0, d.amount)); })
.attr("y", function(d) { return y0(d.agency); })
.attr("width", function(d) { return Math.abs(xScale(d.amount) - xScale(0)); })
.attr("height", y0.rangeBand());
//Append baseline
var baseline = svg.append("line")
.attr("y2", function(d) { return height; })
.attr("class", "added-baseline")
.attr("x1", xScale(0))
.attr("x2", xScale(0))
.attr("stroke-width", 1)
.attr("stroke", "#333333");
//Binds data to axis text
var axisLabelGroup = svg.selectAll("g-axis-text")
.data(initialType)
.enter()
.append("g")
.attr("class", "g-axis-text")
.attr("x", function(d) { return xScale(Math.min(0, d.amount)); })
.attr("y", function(d) { return y0(d.agency); })
.attr("width", function(d) { return Math.abs(xScale(d.amount) - xScale(0)); })
.attr("height", y0.rangeBand());
//Append axis labels
var axisLabels = axisLabelGroup.append("text")
.text(function(d) { return d.agency; })
.attr("x", function(d) { return xScale(0); })
.attr("y", function(d) { return y0(d.agency) + 17; });
d3.selectAll(".g-axis-text")
.attr("transform", "translate(-265,0)");
//Update chart on click
function updateChartForType(typeId) {
//Filters to the new data
var typeData = data.filter(function(d) { return d.type === typeId;});
//Updates domains
xScale.domain(d3.extent(typeData, function(d) { return d.amount; })).nice();
y0.domain(data.map(function(d) { return d.agency; }));
bars
.data(typeData)
.transition().duration(1000)
.attr("x", function(d) { return xScale(Math.min(0, d.amount)); })
.attr("width", function(d) { return Math.abs(xScale(d.amount) - xScale(0)); });
xAxisGroup
.transition().duration(1000)
.call(xAxis);
yAxisGroup
.transition().duration(1000)
.call(yAxis);
baseline
.transition().duration(1000)
.attr("x1", xScale(0))
.attr("x2", xScale(0))
}
//RESPONSIVENESS
d3.select(window).on("resize", resized);
function resized() {
//new margin
var newMargin = {top: 0, right: 6, bottom:30, left: 170};
var newWidther = d3.select(".gia-chart").node().clientWidth;
var newWidth = newWidther - newMargin.left - newMargin.right;
//Change the width of the svg
d3.select("svg")
.attr("width", newWidth + newMargin.left + newMargin.right);
//Change the xScale
xScale
.range([0, newWidth]);
//Update the bars
bars
.attr("width", function(d) { return Math.abs(xScale(d.amount) - xScale(0)); })
.attr("x", function(d) { return xScale(Math.min(0, d.amount)); })
//Updates xAxis
d3.selectAll(".x.axis")
.call(xAxis);
//Updates ticks
xAxis
.scale(xScale);
//Updates yAxis
d3.selectAll(".y.axis")
.attr("transform", "translate(" + xScale(0) + ",0)")
.call(yAxis);
yAxis
.tickSize(-newWidth);
baseline
.attr("x1", xScale(0))
.attr("x2", xScale(0));
};
}
</script>
</body>
</html>
https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js