Skip to content

Instantly share code, notes, and snippets.

@1Cr18Ni9
Last active January 10, 2017 13:09
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 1Cr18Ni9/b85f7230e5c31bfc279a8ab0b1cd72ec to your computer and use it in GitHub Desktop.
Save 1Cr18Ni9/b85f7230e5c31bfc279a8ab0b1cd72ec to your computer and use it in GitHub Desktop.
Grouped BarChart
license: mit

Built with blockbuilder.org

  • This example has a bug that user can interupt the transition even through i add 'end' status at the end of it. Hoping one day i can find out.

  • The animation is a little uggly because the default animation behavous and my group layout. Whatever.

  • One thing to be mention, if you chain the selection, transition and on-event, it will not work. I think the chained returned selection is not appropriate for others.

Country Electronics Software Mechanics
Germany 12 14 18
Italy 8 12 10
Spain 6 4 5
France 10 14 9
UK 7 11 9
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v3.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
</style>
</head>
<div id='container'></div>
<body>
<script>
var url = 'data.csv'
d3.csv(url, function(error, data){
// major dimension
var margin = {top: 70, bottom: 40, left: 40, right: 120}, axisPadding = 5;
var WIDTH = 450, HEIGHT = 300;
var svgWidth = WIDTH + margin.left + margin.right,
svgHeight = HEIGHT + margin.top + margin.bottom;
var svg = d3.select('#container')
.append('svg')
.attr({width: svgWidth, height: svgHeight});
var items = d3.keys(data[0]).filter(function(d){ return d !== 'Country'; })
// Country,Electronics,Software,Mechanics
var nest = d3.nest()
.key(function(d){ return d.Country; })
.sortKeys(d3.ascending)
.rollup(function(leave){
return items.map(function(e){return {name: e, value: +leave[0][e]}})
})
.entries(data);
var maxIncome = d3.max(nest, function(d0){
return d3.max(d0.values, function(d1){return d1.value; });
});
// create scales and axises
var xScale = d3.scale.ordinal()
.domain(nest.map(function(d){ return d.key; }))
.rangeBands([0, WIDTH], 0.15);
var xInner = d3.scale.ordinal()
.domain(items)
.rangeBands([0, xScale.rangeBand()], 0);
var color = d3.scale.category10()
.domain(items);
// console.log(xScale.domain())
var yScale = d3.scale.linear()
.domain([0, maxIncome])
.range([0, HEIGHT]);
var xAxis = d3.svg.axis()
.orient('bottom')
.tickSize(6,0)
.scale(xScale);
var yAxis = d3.svg.axis()
.orient('left')
.ticks(5)
.scale(yScale.copy().domain(yScale.domain().slice().reverse()));
// console.log(yScale.domain());
var xGroup = svg.append('g')
.attr('transform', 'translate(' +
[margin.left, margin.top + HEIGHT + axisPadding] +
')');
xGroup.call(xAxis);
styleAxis(xGroup);
var yGroup = svg.append('g')
.attr('transform', 'translate(' +
[margin.left - axisPadding, margin.top] +
')')
yGroup.call(yAxis);
styleAxis(yGroup);
// create the body graph
var mainGroup = svg.append('g')
.attr('transform', 'translate(' +
[margin.left, margin.top + HEIGHT] +
')');
var countries = mainGroup.selectAll('g')
.data(nest)
.enter()
.append('g')
.attr('transform', function(d){
return 'translate(' + [xScale(d.key), 0] + ')';
});
var rects = countries.selectAll('rect')
.data(function(d){return d.values;})
.enter()
.append('rect')
.each(function(d,i){
d3.select(this).attr({
fill: color(d.name),
x: xInner(d.name),
y: 0,
height: yScale(d.value),
width: xInner.rangeBand(),
});
});
// animation
rects
.transition()
.duration(600)
.each('end', function(d){
d3.select(this)
.transition()
.attr('y', -yScale(d.value))
})
.attr('y', function(d){ return -yScale(d.value); });
// add interactive behavious
rects
.on('mouseover', function(){
d3.select(this)
.transition()
.attr('fill', 'yellow')
})
.on('mouseout', function(){
d3.select(this)
.transition()
.delay(200)
.attr('fill', function(d){ return color(d.name); })
});
// text label
countries.selectAll('text')
.data(function(d){return d.values;})
.enter()
.append('text')
.each(function(d,i){
d3.select(this).text(d.value);
d3.select(this).attr({
x: xInner(d.name) + xInner.rangeBand() / 2,
y: -yScale(d.value) - 3,
'text-anchor': 'middle',
});
});
// create legend
var legendGroup = svg.append('g')
.attr('transform', 'translate(' +
[margin.left + WIDTH + axisPadding, margin.top] +
')');
var legends = legendGroup.selectAll('g')
.data(items)
.enter()
.append('g')
.attr('transform', function(d,i){return 'translate(' + [0, i * 25] + ')'});
legends.append('rect')
.attr({
fill: function(d){return color(d)},
rx: 10,
ry: 10,
width: 20,
height: 20,
});
legends.append('text')
.text(function(d){return d;})
.attr({
fill: 'black',
x: 25,
y: 16,
});
})
function styleAxis(axis){
// style path
axis.select('.domain').attr({
fill: 'none',
stroke: '#888',
'stroke-width': 1
});
// style tick
axis.selectAll('.tick line').attr({
stroke: '#000',
'stroke-width': 1,
})
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment