This time, sort function is cleaner than the previous one. It doesn't need to update rect and text position, just the container g. And, by using 'transform', appending rect and text becomes easier.
A Pen by Hidenari Nozaki on CodePen.
This time, sort function is cleaner than the previous one. It doesn't need to update rect and text position, just the container g. And, by using 'transform', appending rect and text becomes easier.
A Pen by Hidenari Nozaki on CodePen.
<div id="main"> | |
<h1>D3 Grouping Elements: Part 2</h1> | |
<h2>click a bar to sort</h2> | |
</div> |
//Width and height | |
var w = 600; | |
var h = 250; | |
var numset = [ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13, 11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ]; | |
var ascending = true; | |
var dataset = [], index = 0; | |
for (; index < numset.length; index++) { | |
dataset.push({k: index, v: numset[index]}); | |
}; | |
var xScale = d3.scale.ordinal() | |
.domain(d3.range(dataset.length)) | |
.rangeRoundBands([0, w], 0.05); | |
function key(d) { return d.k; } | |
var yScale = d3.scale.linear() | |
.domain([0, d3.max(dataset, function(d) { return d.v; })]) | |
.range([0, h]); | |
var sortBars = function() { | |
var sortFn = ascending ? d3.ascending : d3.descending; | |
svg.selectAll('g.bar') | |
.sort(function(a, b) { return sortFn.call(d3, a.v, b.v); }) | |
.transition() | |
.delay(function(d, i) { return i * 50; }) | |
.duration(1000) | |
.attr('x', function(d, i) { return xScale(i) + xScale.rangeBand(); }) | |
.select('g') | |
.attr("transform", function(d, i) { | |
return "translate(" + xScale(i) + "," + 0 + ")"; | |
}); | |
ascending = !ascending; | |
}; | |
//Create SVG element | |
var svg = d3.select("#main") | |
.append("svg") | |
.attr('margin', '10') | |
.attr("width", w) | |
.attr("height", h); | |
//Create g | |
var bars = svg.selectAll("g") | |
.data(dataset, key) | |
.enter() | |
.append('g') | |
.attr('x', function(d, i) { return xScale(i) + xScale.rangeBand(); }) | |
.attr('width', xScale.rangeBand() + 10) | |
.attr('height', h) | |
.attr('class', 'bar') | |
.append('g') | |
.attr("transform", function(d, i) { | |
return "translate(" + xScale(i) + "," + 0 + ")"; | |
}) | |
.on('click', function() { sortBars(); }); | |
//Create bars | |
bars.append("rect") | |
.attr("x", 0) | |
.attr("y", function(d) { return h - yScale(d.v); }) | |
.attr("width", xScale.rangeBand()) | |
.attr("height", function(d) { return yScale(d.v); }) | |
.attr("fill", function(d) { return "rgb(0, 0, " + (d.v * 10) + ")"; }); | |
//Create labels | |
bars.append("text") | |
.text(function(d) { return d.v; }) | |
.attr("text-anchor", "middle") | |
.attr("x", function(d, i) { return xScale.rangeBand() / 2; }) | |
.attr("y", function(d) { return h - yScale(d.v) + 14; }) | |
.attr("font-family", "sans-serif") | |
.attr("font-size", "11px") | |
.attr("fill", "white"); |
#main { | |
text-align: center; | |
} | |
svg text { | |
pointer-events: none; | |
} | |
rect { | |
-moz-transition: all 0.3s; | |
-webkit-transition: all 0.3s; | |
transition: all 0.3s; | |
} | |
rect:hover { | |
fill: orange; | |
} |