Skip to content

Instantly share code, notes, and snippets.

@mostaphaRoudsari
Created July 17, 2017 13:07
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 mostaphaRoudsari/b65c971877b2950a3f38332eb8c24400 to your computer and use it in GitHub Desktop.
Save mostaphaRoudsari/b65c971877b2950a3f38332eb8c24400 to your computer and use it in GitHub Desktop.
08_workshop_animated horizontal bar chart
license: mit
Team GP W D L GF GA GD PTS
Chelsea 26 18 6 2 56 22 34 60
Man_City 26 16 7 3 56 25 31 55
Arsenal 26 14 6 6 49 29 20 48
Man_United 26 13 8 5 44 26 18 47
Southampton 25 14 4 7 38 17 21 46
Tottenham 25 13 4 8 39 34 5 43
Liverpool 25 12 6 7 36 29 7 42
West_Ham 25 10 8 7 36 28 8 38
Swansea_City 26 10 7 9 30 34 -4 37
Stoke_City 26 10 6 10 30 34 -4 36
<!DOCTYPE html>
<head>
<title>d3js workshop - animated bar charts</title>
<script src="http://d3js.org/d3.v3.js"></script> <!-- import D3 library -->
</head>
<style type="text/css">
text {
fill: white;
font: 10px sans-serif;
text-anchor: end;
}
</style>
<body>
<div class = "circles"></div>
<div class = "barChart"></div>
<script type="text/javascript">
// this is a modified version of Mike's example here: http://bost.ocks.org/mike/bar/2/
// for this example we will draw rectangles for each bar
// the length of the bar chart will be number of points for each team and we will add a button to change it to wins
// we will learn about axes and scales and will review what we have learned so far
// initial variables
var dataPath = "2015.02.21.PremierLeagueTable.csv",
width = 720,
barHeight = 20;
// this is a linear scale for x
var x = d3.scale.linear()
.range([0, width]); // set the range between 0 and width of the graph
var color = d3.scale.linear()
.range(["blue", "red"]); // set the color range
// read data using d3.csv
d3.csv(dataPath, function(data){
// let's see the data first
//console.log(data);
// coerce values to numbers
// this is javascript - has nothing to do with d3
data.map(function(d){
d.PTS = +d.PTS;
d.W = +d.W;
d.clicked = false; // add a new key to keep track of
});
// before we want to draw the rectangles we need to set the domain for the scale
// so we can use the scale to generate the width of each bar
// we want the length to be based on the points of each team so I return d.PTS
// to set the maximum value
x.domain([0, d3.max(data, function(d){ return d.PTS;})]);
color.domain([d3.min(data, function(d){ return d.W;}), d3.max(data, function(d){ return d.W;})]); // set the domain based on number of wins
// add circles
var circleSize = Math.min(barHeight, width/data.length);
// add svg for circles
var circles = d3.select('.circles')
.append('svg')
.attr('width', width)
.attr('height', circleSize); // set height based on length of data
var button = circles.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d, i) { return "translate(" + i * circleSize + ", 0)"; }); // move each group to it's position
// add circles
button.append("circle")
.attr("r", circleSize/3)
.attr("cx", circleSize/2)
.attr("cy", circleSize/2)
.attr("id", function(d) { return d.Team;})
.style("fill", function(d){return color(d.W);})
.on("click", update); //update is a function that you can find it down there
// add title to circles - browser will take care of tooltip
button.append("title").text(function(d) { return d.Team;});
// now that the scale is ready let's add an svg first and set it's height and width
// Note: chart in this case is an svg! naming in d3 examples can be really confusing
// so make sure to name your object carefully
var chart = d3.select('.barChart')
.append('svg')
.attr('width', width)
.attr('height', data.length * barHeight); // set height based on length of data
// start drawing the bar chart
// here bar will be list of groups which will include the rectangle and the text!
// and I didn't name it bars - this is the common practice in d3js world so you better get used to it
var bar = chart.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d, i) { return "translate(0," + i * barHeight + ")"; }); // move each bar to it's position
// append a rectangle to each group
// note that since the group is already positioned you don't need to move the rectangles
bar.append("rect")
.attr("width", function(d) { return x(d.PTS); }) // here we are using the scale that we created up there
.attr("height", barHeight - 1) // 1 is the padding value so the bars don't touch each other
.attr("id", function(d) { return d.Team;})
.style("fill", function(d){return color(d.W);})
.on("click", update);
// let's add the text and celeberate the almost end of this example
bar.append("text")
.attr("x", function(d) { return x(d.PTS) - 3; }) // move the text to the end of the chart
.attr("y", barHeight / 2) // and move the insertion point to the center of the bar
.attr("id", function(d) { return d.Team;})
.attr("dy", ".35em")
.text(function(d) { return d.PTS;});
// add title to bars - browser will take care of tooltip
bar.append("title").text(function(d) { return d.Team;});
// try to add a similar behavior to bars itself so once you click they
});
function update(){
// find the id of the selected circle
var id = d3.select(this).attr("id");
// select rectangle and update the width
d3.select("rect#" + id)
.transition()
.duration('1000')
.attr('width', function(d){
debugger;
d.clicked = !d.clicked;
return d.clicked? barHeight:x(d.PTS); // expand it back
});
// select text and move it back
d3.select("text#"+id)
.transition('ease')
.duration('1000')
.delay(function(d){
return d.clicked? 0:200; // adding delay on expansion
})
.attr('x', function(d){
return d.clicked? barHeight-3: x(d.PTS)-3;
});
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment