Pergunta

Hello I do an sunburst or bilevel chart it's middle of a pie & donut chart ^^ When I append all path it works fine:

this.path = this.svg.selectAll("path")
.data(this.partition.nodes(rootData).slice(1))
.enter().append("path")
.attr("d", this.arc)
.style("fill", function(d) { return d.fill; })
.each(function(d){ this._current = thiss.updateArc(d);});

But the probleme is when I'm trying to add a circle in middle-extern of all my path so it didn't work, this code add circle in the middle-middle of all my path fine

var indicator =  this.svg.selectAll('circle')
.data(this.partition.nodes(rootData))
.enter().append("circle")
.attr("cx", function(d){return thiss.arc.centroid(d)[0]})
.attr("cx", function(d){return thiss.arc.centroid(d)[1]})
.attr("r", 5).style('fill','#ff0000');

But I need to add this little circle in the midle but on extern border of the path. I don't know how I can get the right cx and cy attributs, help please ?

This is screenshot of my goal (black points are what I had) and (red points are what I want to do)

http://i.stack.imgur.com/GXPYM.jpg

enter image description here

Foi útil?

Solução

This is in part a repeat of Lars' equations from the comments, but I thought it was worth recapping all at once because the trig identities for converting from angles to x/y coordinates won't match your trig text book.

Most text books assume that angles start at the right horizontal axis and increase counter-clockwise, and that the vertical axis has larger values higher up on the page.

In SVG, larger y values are lower on the page, and the angles created by the pie chart layout (and the example code the OP is using for the sunburst layout) draw an angle of zero as vertical line to the top of the circle, with angles increasing clockwise.

With that information, you can convert to x and y values with the following trig equations:

  g.append("circle") //circles inherit pie chart data from the <g>
      .attr("r", 5) 
      .attr("cx", function(d) { 
          return Math.sin((d.startAngle + d.endAngle)/2) *radius;
      })
      .attr("cy", function(d) { 
          return -Math.cos((d.startAngle + d.endAngle)/2) *radius;
      });

Live example: http://fiddle.jshell.net/4x9ap/1/

Again, this simple example uses a pie chart layout, so the data has startAngle and endAngle values, and the radius is constant. For a sunburst diagram made with the partition layout, you would replace (d.startAngle + d.endAngle)/2 with d.x + d.dx/2, and you would replace radius with a function based on d.depth.

Outras dicas

As an alternative to trigonometry, you could use transformations to position the circles. If the first step in a transformation is a rotation, and then you apply a translation afterwards, the translation will be applied in the rotated coordinate system.

A little extra complication, though, is that the d3 pie chart gives angles in radians (since that's what the trigonometry functions use), but the rotation needs angles in degrees.

  var degreesPerRadian = 180/Math.PI;
  g.append("circle") //circles inherit pie chart data from the <g>
      .attr("r", 5)
      .attr("transform", function(d) { 
          return "rotate(" +  degreesPerRadian*((d.startAngle + d.endAngle)/2) 
          + ")" +
              //rotate by the average of the start and end angle
              //Note that d3 specifies angles in radians, but the rotate
              //function needs them in degrees
              "translate(0," + -radius + ")";
              //then translate "up" the distance of the radius;
              //"up" is interpretted according to the rotated coordinates,
              //but for zero rotation it will position the dot at the top
              //of the circle, which is the zero angle for d3
      });

Live example: http://fiddle.jshell.net/4x9ap/

(based on this simple pie chart code )

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top