Chris Johnson
Chris Johnson

Reputation: 187

Rotate Donut Chart to Middle of Selected Slice

I'd like to rotate my donut/pie chart so that the middle of the selected slice is centered at the top. Rotating the chart with transform(rotate) is simple enough, the question is, how does one find the angle to rotate it at so that slice is centered at top. Thank you!

Currently, I select the slice by:

slice.on('click', function(d){
    console.log(d);
    //etc //etc
})

Upvotes: 0

Views: 292

Answers (1)

Ruben Helsloot
Ruben Helsloot

Reputation: 13129

Using this example as a base, when you click on a donut, it moves itself to the top. Remember to transform from radians to degrees!

const pie = d3.pie()
  .padAngle(0.005)
  .sort(null)
  .value(d => d.value);

const height = 400,
  width = 600;
const radius = Math.min(width, height) / 2
const arc = d3.arc()
  .innerRadius(radius * 0.67)
  .outerRadius(radius - 1);
const svg = d3.select('svg')
  .attr('height', height)
  .attr('width', width)
  .attr("viewBox", [-width / 2, -height / 2, width, height]);
const g = svg.append('g');

d3.csv("https://static.observableusercontent.com/files/bee673b386dd058ab8d2cf353acbedc6aa01ebd1e6f63e2a9ab1b4273c7e6efd1eeea526345e4be7f0012d5db3ec743ef39ad9e6a043c196670bf9658cb02e79?response-content-disposition=attachment%3Bfilename*%3DUTF-8%27%27population-by-age.csv").then(data => {
  const color = d3.scaleOrdinal()
    .domain(data.map(d => d.name))
    .range(d3.quantize(t => d3.interpolateSpectral(t * 0.8 + 0, 1), data.length).reverse());

  const arcs = pie(data);

  const slice = g
    .selectAll("path")
    .data(arcs)
    .join("path")
    .attr("fill", d => color(d.data.name))
    .attr("d", arc);

  slice
    .append("title")
    .text(d => `${d.data.name}: ${d.data.value.toLocaleString()}`);

  slice.on("click", (event, d) => {
    const centerAngle = (d.endAngle - d.startAngle) / 2 + d.startAngle;
    g.transition()
      .duration(500)
      .attr('transform', `rotate(-${centerAngle / (2 * Math.PI) * 360})`);
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script>
<svg></svg>

Upvotes: 2

Related Questions