I'm a total beginner with D3 and have started by plotting some data retrieved from an API, e.g:
chartData = [
{ track: "A Kind of Magic", playcount: 2683110 },
{ track: "Another One Bites the Dust", playcount: 6425611 },
{ track: "Bohemian Rhapsody", playcount: 10167011 },
{ track: "Crazy Little Thing Called Love", playcount: 4360128},
{ track: "Don't Stop Me Now", playcount: 7762976 },
{ track: "Flash", playcount: 1248561 }];
Following some online examples, I have rendered the bar chart:
var margin = {
top: 50,
right: 40,
bottom: 80,
left: 100
},
width = 1200 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var svg = d3.select('#queenChart')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.append('g').attr('transform', `translate(${margin.left}, ${margin.top})`);
var x = d3.scaleBand()
.domain(chartData.map(d => d.track))
.range([0, width])
.padding(0.1);
svg.append('g')
.attr('transform', `translate(0, ${height})`)
.call(d3.axisBottom(x))
.selectAll('text')
.attr('transform', 'translate(-10,0) rotate(-45)')
.style('text-anchor','end');
var y = d3.scaleLinear()
.domain([0, d3.max(chartData, d => { return d.playcount; })])
.range([height, 0]);
svg.append('g')
.call(d3.axisLeft(y));
svg.selectAll('rect')
.data(chartData)
.enter()
.append('rect')
.style('fill', 'steelblue')
.attr('x', d => x(d.track))
.attr('y', d => y(d.playcount))
.attr('height', d => { return height - y(d.playcount); })
.attr('width', x.bandwidth );
The problem comes when I attempt to sort the chart:
setTimeout(() => {
svg.selectAll('rect')
.sort((a,b) => d3.ascending(a.playcount, b.playcount))
.transition()
.duration(500)
.attr('x', d => x(d.track));
}, 2500);
After 2.5 seconds I can see that all of the <rect> elements in the DOM have indeed sorted correctly, but the chart svg itself is completely unchanged. Is there something I'm missing that gets the chart to rerender to reflect the changes in the DOM?