Reputation: 787
I am trying to create a radial (circular) grouped bar chart with d3.js, something like that.
To do it, I started from three examples:
To make it simple, I am using the same data of the first example and I deleted labels and axis, I left only scales's function and arc generator. I think I am not to far from the final solution, but I can not figure out what I am missing/doing wrong, but I think it could be x0's function or the translate of each bar in the same group. As you can see, no one bar or group is correctly positioned.
I prepare an example here.
Some code here:
X scale function, to position each group:
x0 = d3.scaleBand()
.domain(data.map(d => d.State))
.range([0, 2 * Math.PI])
.align(0)
X scale function, to position each bar in group:
x1 = d3.scaleBand()
.domain(keys)
.range([0, x0.bandwidth()])
.align(0)
Y scale function, to position height of bar:
y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.total)])
.range([innerRadius, outerRadius]);
Arc generator:
arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius((d) => y(d.value))
.startAngle(d => x1(d.key))
.endAngle(d => x1(d.key) + x1.bandwidth())
.padAngle(0.01)
.padRadius(innerRadius)
Main chain:
svg.append("g")
.selectAll("g")
.data(data)
.join("g")
.attr("transform", d => `translate(${x0(d[groupKey])},0)`)
.selectAll("path")
.data(d => keys.map(key => ({key, value: d[key]})))
.join("path")
.attr('fill', '#69b3a2')
.attr("d", arc);
Upvotes: 1
Views: 2913
Reputation: 6792
Yep, you were close. I changed a couple things on your observable that seemed to fix it.
First, in your main graph function, you're using translate
instead of rotate
:
// ...
svg.append("g")
.selectAll("g")
.data(data)
.join("g")
// .attr("transform", d => `translate(${x0(d[groupKey])},0)`)
.attr("transform", d => `rotate(${x0(d[groupKey])})`) // use rotate (also remove ',0')
.selectAll("path")
.data(d => keys.map(key => ({key, value: d[key]})))
.join("path")
.attr('fill', '#69b3a2')
.attr("d", arc);
// ...
Second, rotate
as a transform requires degrees, but x0
returns radians since that's what d3.arc
needs. The simplest fix I could find for this is just adding a conversion from rads to degs in the rotate
transform:
// ...
svg.append("g")
.selectAll("g")
.data(data)
.join("g")
// .attr("transform", d => `translate(${x0(d[groupKey])},0)`)
// .attr("transform", d => `rotate(${x0(d[groupKey])})`)
.attr("transform", d => `rotate(${x0(d[groupKey]) * 180 / Math.PI})`)
.selectAll("path")
.data(d => keys.map(key => ({key, value: d[key]})))
.join("path")
.attr('fill', '#69b3a2')
.attr("d", arc);
// ...
This gives what I imagine starts to be the correct results:
Upvotes: 2