Reputation: 1
I have a Horizontal bar chart in D3, but I'd like to have a vertical bar chart instead of a horizontal. Here's what it looks like now. I tried fiddling with the X and Y axes and can't seem to get it right. Any help would be greatly appreciated.
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<title>Layered Bar Chart</title>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
</head>
<body>
<script>
var dataArray = [10, 20, 40, 60];
var canvas = d3.select("body")
.append("svg")
.attr("width", 500).attr("height", 500);
var bars = canvas.selectAll("rect")
.data(dataArray)
.enter()
.append("rect")
.attr('class', 'base')
.attr("width", function(d){
return d * 10;
})
.attr("height", 30)
.attr("y", function(d, i){
return i * 35;
})
.attr("fill", "blue");
//.attr("fill-width", "green");
/*
canvas.append("text")
.text(function(d){
return d;
}).attr;
*/
var dataArray1 = [5, 10, 20, 30];
var bars1 = canvas.selectAll("rect.addon")
.data(dataArray1)
.enter()
.append("rect")
.attr('class', 'addon')
.attr("width", function(d){
return d * 7;
})
.attr("height", 20)
.attr("y", function(d, i){
return (i*35) + 5;
})
.attr("fill", "red");
//.attr("fill-width", "black");
</script>
</body>
</html>
Upvotes: 0
Views: 2038
Reputation: 38161
For this type of conversion you need to change more than x and y.
Using your example code, the chart's shape will be dictated by the four properties of each rectangle: x
, y
, width
, and height
. Afterall, (generally) a vertical bar chart does not have the same height for each bar, while a horizontal bar chart does.
Secondly, most vertical bar charts have the rects anchored on the bottom while most horizontal bar charts have the rects anchored to the left. In svg coordinate space the top of the svg is y = 0, while the left of the svg is x = 0. Consequently, simply swapping x
and y
, width
and height
in your example will result in a bar chart that has bars reaching down from the top of the chart.
To solve this, you need to modify the y
attribute of each rectangle. As the y
attribute sets the top of the rectangle, you need to figure out the top of each rectangle. For your code:
.attr("y", function(d,i) { return heightOfSVG - heightOfRectangle; }) // bottom of rectangle - rectangle height = rectangle top
This line is new as you didn't set the x attribute in your original code, instead using the default zero. This won't do in the vertical graph, as the top of the rectangle can't be at y = 0 (in most cases).
The use of scales of course will complicate this, as will labelled axes, or multiple-series bar charts etc. I've used your code, as it was provided. I've stripped your example to one chart as opposed to two to show what those changes might look like applied to a minimal example of a scale-less graph.
var canvas = d3.select("body")
.append("svg")
.attr("width", 500).attr("height", 500);
var bars = canvas.selectAll("rect")
.data([10, 20, 40, 60])
.enter()
.append("rect")
.attr("height", function(d){
return d * 10;
})
.attr("width", 30)
.attr("x", function(d, i){
return i * 35;
})
.attr("y", function(d,i) { return 500 - d * 10; })
.attr("fill", "blue");
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
Upvotes: 1