Skip to content

Instantly share code, notes, and snippets.

@alandunning
Last active November 14, 2017 23:50
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 alandunning/24bdfd1538006591a38b5096b70ca024 to your computer and use it in GitHub Desktop.
Save alandunning/24bdfd1538006591a38b5096b70ca024 to your computer and use it in GitHub Desktop.
Reading - 3 Bars Grouped Bar Chart with Pulse D3 V4
license: gpl-3.0

This grouped bar chart is constructed from a CSV file storing the populations of different states by age group. The chart employs conventional margins and a number of D3 features:

forked from mbostock's block: Grouped Bar Chart

forked from alandunning's block: Reading - Grouped Bar Chart D3 V4

forked from anonymous's block: Reading - 3 Bars Grouped Bar Chart with Pulse D3 V4

State Pre-treatment Post Treatment Post Treatment2
Seperation Anxiety 80 73 71
Generalised Anxiety 77 75 73
Panic 75 73 79
Socail pHOBIA 81 70 70
OCD 66 65 68
Depression 75 74 79
0 0 0
Total Anxiety 77 73 70
Total Anxiety & Depression 81 69 77
<!DOCTYPE html>
<style>
.axis .domain {
display: none;
}
body {
font-family: 'Droid Sans', sans-serif;
}
.axis {
font-size: 14px;
font-weight: bold;
}
text {
fill: #727075;
stroke: none;
}
.axis path,
.axis line {
fill: none;
stroke: none;
stroke-width: 2px;
shape-rendering: crispEdges;
}
.grid path {
stroke: none;
}
.grid line {
stroke: #E0E0E0;
shape-rendering: crispEdges;
}
.data-line {
fill: none;
stroke: #3C92BA;
stroke-width: 4px;
}
.data-circle {
fill: #3C92BA;
}
.axis-title {
text-anchor: end;
fill: #5D6971;
font-weight: normal;
}
.axis-tspan {
font-size: 12px;
}
.clinical-cut-off-line {
fill: none;
stroke: #333333;
stroke-dasharray: 8,8;
stroke-width: 4px;
}
.clinical-cut-off-text {
text-transform: uppercase;
text-anchor: start;
font-size: 12px;
font-weight: bold;
fill: #333333;
stroke: none
}
@-webkit-keyframes pulse {
0% {opacity: 1;}
50% {opacity: 0.3;}
100% {opacity: 1;}
}
.bars-container-middle {
fill: none;
stroke: none;
}
.clinically-significant-pulsing-rect {
fill: pink;
/* Giving Animation Function */
-webkit-animation: pulse 1.5s ease infinite;
}
</style>
<link href="https://fonts.googleapis.com/css?family=Droid+Sans:400,700" rel="stylesheet">
<svg width="730" height="375"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var svg = d3.select("svg"),
margin = {top: 20, right: 20, bottom: 30, left: 40},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom,
g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x0 = d3.scaleBand()
.rangeRound([0, width])
.paddingInner(0.2);
var x1 = d3.scaleBand()
.padding(0.1);
var y = d3.scaleLinear()
.rangeRound([(height / 1.75), 0]);
var z = d3.scaleOrdinal()
.range(["#37A3D6", "#FF9400", "#ff0000"]);
var clinicalCutOffValue = 65;
d3.csv("data.csv", function(d, i, columns) {
for (var i = 1, n = columns.length; i < n; ++i) d[columns[i]] = +d[columns[i]];
return d;
}, function(error, data) {
if (error) throw error;
var keys = data.columns.slice(1);
x0.domain(data.map(function(d) { return d.State; }));
x1.domain(keys).rangeRound([0, x0.bandwidth()]);
y.domain([
(Math.floor(d3.min(data, function(d) { return d3.max(keys, function(key) { return d[key]; }); }) / 10) * 10),
(Math.ceil(d3.max(data, function(d) { return d3.max(keys, function(key) { return d[key]; }); }) / 10) * 10)
]);
var legend = g.append("g")
.attr("class", "legend")
.selectAll("g")
.data(keys.slice().reverse())
.enter()
.append("g")
.attr("transform", function(d, i) { return "translate(" + i * (width / keys.length) + ", 0)"; });
legend.append("rect")
.attr("x", 0)
.attr("width", 20)
.attr("height", 20)
.attr("fill", z);
legend.append("text")
.attr("x", 25)
.attr("y", 9.5)
.attr("dy", "0.32em")
.text(function(d) { return d; });
// add the Y gridlines
g.append("g")
.attr("class", "grid")
.attr("transform", "translate(0," + (height / 7) + ")")
.call(d3.axisLeft(y)
.tickSize(-width)
.tickFormat("")
.ticks(6)
);
var barG = g.append("g")
.selectAll("g")
.data(data)
.enter()
.append("g")
.attr("transform", function(d) { return "translate(" + x0(d.State) + ",0)"; });
barG.selectAll(".bars-container-middle")
.data(function(d) { return keys.map(function(key) { return {key: key, value: d[key]}; }); })
.enter()
.append("rect")
.attr("class", function(d) {
if (d.value > 75) return 'bars-container-middle clinically-significant-pulsing-rect';
else return 'bars-container-middle';
})
.attr("transform", "translate(0," + (height / 7) + ")")
.attr("x", function(d) { return x1(d.key); })
.attr("y", function(d) { return 0; })
.attr("width", x1.bandwidth())
.transition()
.delay(function (d,i){ return 750;}) // this is to do left then right bars
.duration(250)
.attr('height', function( d ) { return ((height / 1.75));});;
barG.selectAll(".bars")
.data(function(d) { return keys.map(function(key) { return {key: key, value: d[key]}; }); })
.enter()
.append("rect")
.attr("class", "bars")
.attr("transform", "translate(0," + (height / 7) + ")")
.attr("x", function(d) { return x1(d.key); })
.attr("width", x1.bandwidth())
.attr("fill", function(d) { return z(d.key); })
.attr("y", (height / 2))
.transition()
.delay(function (d,i){ return i * 250;}) // this is to do left then right bars
.duration(250)
.attr("y", function(d) { return y(d.value); })
.attr('height', function( d ) { return ((height / 1.75)) - y( d.value );});
g.append("g")
.attr("class", "x-axis axis")
.attr("transform", "translate(0," + (height / 1.4) + ")")
.call(d3.axisBottom(x0))
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("transform", "rotate(-65)")
.text(function (d) {
if(d.length > 14) { return d.substring(0,14)+'...'; }
else { return d; }
});
g.append("g")
.attr("class", "y-axis axis")
.attr("transform", "translate(0," + (height / 7) + ")")
.call(d3.axisLeft(y).ticks(6));
// Clinicial cut off line and text group
var clinicalCutOffLineAndText = g.append("g")
.attr("class", "clinical-cut-off-line-and-text")
.attr("transform", "translate(0," + (height / 7) + ")")
// Clinicial cut off line
clinicalCutOffLineAndText.append("line")
.attr("class", "clinical-cut-off-line")
.attr("x1", 0)
.attr("y1", y(clinicalCutOffValue))
.attr("x2", width)
.attr("y2", y(clinicalCutOffValue));
// Clinicial cut off text
clinicalCutOffLineAndText.append("text")
.attr("class", "clinical-cut-off-text")
.attr("y", y(clinicalCutOffValue))
.attr("dy","20px")
.text("Clinical Cut-off");
});
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment