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.



enter image description here


<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.





What about this stackoverflow.com/questions/21960582/… ?
– MiXT4PE
Jun 29 at 22:52




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:



enter image description here



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>

Comments

Popular posts from this blog

paramiko-expect timeout is happening after executing the command

Export result set on Dbeaver to CSV

Opening a url is failing in Swift