D3 Bar graph mirror [duplicate]
D3 Bar graph mirror [duplicate]
This question already has an answer here:
https://jsfiddle.net/cg3xL4da/49/
How would I rotate/translate the D3 graph bars to look like the picture below except the numbers are still aligned all the way right. I've tried switching the range array parameter, but it just flips the bar placement.
<svg class="chart"></svg>
//d3js.org/d3.v3.min.js
var data = [4, 8, 15, 16, 23, 42];
var width = 420,
barHeight = 20;
var x = d3.scale.linear()
.domain([0, d3.max(data)])
.range([0, width]);
var chart = d3.select(".chart")
.attr("width", width)
.attr("height", barHeight * data.length);
var bar = chart.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d, i) { return "translate(0," + i * barHeight + ")"; });
bar.append("rect")
.attr("width", x)
.attr("height", barHeight - 1);
bar.append("text")
.attr("x", function(d) { return x(d) - 3; })
.attr("y", barHeight / 2)
.attr("dy", ".35em")
.text(function(d) { return d; });
<style>
.chart rect {
fill: green;
}
.chart text {
fill: white;
font: 10px sans-serif;
text-anchor: end;
}
</style>
This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.
2 Answers
2
The answer for your question is just a proper understanding of what D3 scales are and how to use them. You were in the right path when you said "I've tried switching the range array parameter".
D3 scales are basically a mathematical way to map a domain (input) to an image or range (output), as I explain in this answer. This image from Jerome Cukier blog is even more didactic:
As you can see, the scale maps 20
in the domain to 0
in the range, and 80
in the domain to 120
in the range.
20
0
80
120
Reverse range
With that in mind the answer to your question is very simple. If you look at your scale right now...
var x = d3.scale.linear()
.domain([0, d3.max(data)])
.range([0, width]);
You'll see that the zero in the data (that is, the domain) is mapped to zero in the SVG space, and the maximum in the data is mapped to width
in the SVG. So, you just need to reverse the range:
width
var x = d3.scale.linear()
.domain([0, d3.max(data)])
.range([width, 0]);
Now, zero in the data is mapped to the far right in the SVG, and the maximum in the data is mapped to zero, the far left in the SVG. After that, you have to adjust the x
and width
attributes of the rects.
x
width
Here is the code with that change:
<svg class="chart"></svg>
//d3js.org/d3.v3.min.js
var data = [4, 8, 15, 16, 23, 42];
var width = 420,
barHeight = 20;
var x = d3.scale.linear()
.domain([0, d3.max(data)])
.range([width, 0]);
var chart = d3.select(".chart")
.attr("width", width)
.attr("height", barHeight * data.length);
var bar = chart.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d, i) {
return "translate(0," + i * barHeight + ")";
});
bar.append("rect")
.attr("x", x)
.attr("width", function(d) {
return width - x(d)
})
.attr("height", barHeight - 1);
bar.append("text")
.attr("x", width - 2)
.attr("y", barHeight / 2)
.attr("dy", ".35em")
.text(function(d) {
return d;
});
<style>
.chart rect {
fill: green;
}
.chart text {
fill: white;
font: 10px sans-serif;
text-anchor: end;
}
</style>
As MiXT4Pe alluded to in the comments, the trick lies in the transform of your g element combined with the x positioning of each bar and text element being set to the individual bar width. See example below:
var data = [4, 8, 15, 16, 23, 42];
var width = 420,
barHeight = 20;
var x = d3.scale.linear()
.domain([0, d3.max(data)])
.range([0, width]);
var chart = d3.select(".chart")
.attr("width", width)
.attr("height", barHeight * data.length);
var bar = chart.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", function(d, i) { return "translate(420," + i * barHeight + ")"; }); //update x position to 420
bar.append("rect")
.attr("x", (d) => { return (x(d) * -1)}) // add this to position everything right
.attr("width", x)
.attr("height", barHeight - 1);
bar.append("text")
.attr("x", -3) // modify this to position text properly
.attr("y", barHeight / 2)
.attr("dy", ".35em")
.text(function(d) { return d; });
.chart rect {
fill: green;
}
.chart text {
fill: white;
font: 10px sans-serif;
text-anchor: end;
}
https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js
<svg class="chart"></svg>
What about this stackoverflow.com/questions/21960582/… ?
– MiXT4PE
Jun 29 at 22:52