Reputation: 3706
I am curious if someone can point out what I am doing wrong here? I was hoping my code would generate a smooth transition on click events, instead, first click only shifts the x-axis labels (why? how do i fix that?), then second/third do the sorting. Is there a way to prevent that from happening? I want to sort on first click and sure it would be nice if my labels didn't jump around. What am I missing here?
http://jsbin.com/cohaziqugo/edit?js,output
var data = [{"name":"A","value":0.08167},{"name":"B","value":0.01492},{"name":"C","value":0.0278},{"name":"D","value":0.04253},{"name":"E","value":0.12702},{"name":"F","value":0.02288},{"name":"G","value":0.02022},{"name":"H","value":0.06094},{"name":"I","value":0.06973},{"name":"J","value":0.00153},{"name":"K","value":0.00747},{"name":"L","value":0.04025},{"name":"M","value":0.02517},{"name":"N","value":0.06749},{"name":"O","value":0.07507},{"name":"P","value":0.01929},{"name":"Q","value":0.00098},{"name":"R","value":0.05987},{"name":"S","value":0.06333},{"name":"T","value":0.09056},{"name":"U","value":0.02758},{"name":"V","value":0.01037},{"name":"W","value":0.02465},{"name":"X","value":0.0015},{"name":"Y","value":0.01971},{"name":"Z","value":0.00074}];
var tickValues = data.map(function (d){return d.name;});
var step = Math.floor(tickValues.length / 24);
var indexes = d3.range(0,tickValues.length, step);
if (indexes.indexOf(tickValues.length - 1) == -1){
indexes.push(tickValues.length - 1);
}
var tickArray = d3.permute(tickValues, indexes);
var margin = { top: 40, right: 20, bottom: 30, left: 40 },
width = 1500 - margin.left - margin.right,
height = 600 - margin.top - margin.bottom;
var x = d3.scale.ordinal()
.domain(data.map(function (d) { return d.name; }))
.rangeBands([0, width], 0.1, 0.35);
var y = d3.scale.linear()
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickValues(tickArray);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var barChart = d3.select("#barbarchart1").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 + ")");
y.domain([0, 0.2]);
barChart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-0.8em")
.attr("dy", "0.15em")
.attr("transform", function(d){
return "rotate(-65)"
});
barChart.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Test");
barChart.selectAll("#bar")
.data(data)
.enter().append("rect")
.attr("id", "bar")
.attr("x", function (d) { return x(d.name); })
.attr("width", x.rangeBand())
.attr("y", function (d) { return y(d.value); })
.attr("fill", "grey")
.attr("height", function (d) { return height - y(d.value); })
.on("click", function() {sortBars();})
.on("mouseover", function(d){
var xPos = parseFloat(d3.select(this).attr("x"));
var yPos = parseFloat(d3.select(this).attr("y"));
var height = parseFloat(d3.select(this).attr("height"));
var width = parseFloat(d3.select(this).attr("width"));
d3.select(this).attr("fill", "red");
barChart.append("text")
.attr("x",xPos)
.attr("y", yPos - 3)
.attr("font-family", "sans-serif")
.attr("font-size", "10px")
.attr("font-weight", "bold")
.attr("fill", "black")
.attr("text-anchor", "middle")
.attr("id", "tooltip")
.attr("transform", "translate(" + width/2 + ")")
.text(d.name +": "+ d.value);
})
.on("mouseout", function(){
barChart.selectAll("#tooltip").remove();
d3.select(this).attr("fill", "grey");
});
var sortOrder = true;
var sortBars = function() {
//Flip value of sortOrder
sortOrder = !sortOrder;
var x0 = x.domain(data.sort(sortOrder
? function(a, b) { return b.value - a.value; }
: function(a, b) { return d3.ascending(a.name, b.name); })
.map(function(d) { return d.name; }))
.copy();
barChart.selectAll("#bar")
.sort(function(a, b) { return x0(a.name) - x0(b.name); });
var transition = barChart.transition().duration(750),
delay = function(d, i) { return i * 50; };
transition.selectAll("#bar")
.delay(delay)
.attr("x", function(d) { return x0(d.name); });
transition.select(".x.axis")
.call(xAxis)
.selectAll("text")
.selectAll("g")
.delay(delay)
;};
function type(d) {
d.value = +d.value;
return d;
}
Upvotes: 0
Views: 80
Reputation: 15982
My solution: http://jsbin.com/cequrabuqi/edit?js,output
first click only shifts the x-axis labels
data
's default sort is ascending. On first click, you flip sortOrder
from true to false, causing your ternary condition to choose
function(a, b) { return d3.ascending(a.name, b.name); })
as the sort order, which is still ascending. While the code is correct, it looks broken because the sort order never changes on the first click, thus nothing happens to the bars on screen.
would be nice if my labels didn't jump around.
I don't fully understand D3, but what seems to happen is when you call transition.select(".x.axis").call(xAxis)
, it removes any styles you have applied. So in my solution, i reapplied the styles each time the sort function is called.
Upvotes: 1