D3饼图元素弹出窗口

时间:2015-07-29 14:27:25

标签: d3.js

我使用D3.js创建了一个简单的饼图,我希望在这些元素的click事件中弹出饼图的每个元素/路径。

以下是我所说的饼图:jsfiddle.net/ankur881120/kt97oq57

arcs.filter(function(d) { return d.endAngle - d.startAngle > .2; }).append("svg:text")
      .attr("dy", ".35em")
      .attr("text-anchor", "middle")
      //.attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")rotate(" + angle(d) + ")"; })
      .attr("transform", function(d) { //set the label's origin to the center of the arc
        //we have to make sure to set these before calling arc.centroid
        d.outerRadius = outerRadius; // Set Outer Coordinate
        d.innerRadius = outerRadius/2; // Set Inner Coordinate
        return "translate(" + arc.centroid(d) + ")rotate(" + angle(d) + ")";

现在我想点击红色元素时弹出红色元素。

寻找所有建议,以解决此问题。

1 个答案:

答案 0 :(得分:3)

我刚刚回答了一个关于这个yesterday的非常相似的问题。你的用例是不同的,所以在我更好的判断下,我会再次回答它。

基本上,添加点击处理程序并将弧“组”(弧和文本标签)转换到一起:

var arcs = vis.selectAll("g.slice")
  // Associate the generated pie data (an array of arcs, each having startAngle,
  // endAngle and value properties) 
  .data(pie)
  // This will create <g> elements for every "extra" data element that should be associated
  // with a selection. The result is creating a <g> for every object in the data array
  .enter()
  // Create a group to hold each slice (we will have a <path> and a <text>
  // element associated with each slice)
  .append("svg:g")
  .attr("class", "slice")    //allow us to style things in the slices (like text)
  // ADDED CLICK HANDLER
  .on('click',function(d,i){
   d3.select(this)
    .transition()
    .duration(500)
    .attr("transform",function(d){
        // this this group expanded out?
        if (!d.data._expanded){
            d.data._expanded = true;
            var a = d.startAngle + (d.endAngle - d.startAngle)/2 - Math.PI/2;
            var x = Math.cos(a) * 20;
            var y = Math.sin(a) * 20;
            // move it away from the circle center
            return 'translate(' + x + ',' + y + ')';                
        } else {
            d.data._expanded = false;
            // move it back
            return 'translate(0,0)';                
        }
    }); 
});

更新了fiddle

完整代码:

var canvasWidth = 300, //width
      canvasHeight = 300,   //height
      outerRadius = 100,   //radius
      color = d3.scale.category20(); //builtin range of colors

    var dataSet = [
      {"legendLabel":"One", "magnitude":20}, 
      {"legendLabel":"Two", "magnitude":40}, 
      {"legendLabel":"Three", "magnitude":50}, 
      {"legendLabel":"Four", "magnitude":16}, 
      {"legendLabel":"Five", "magnitude":50}, 
      {"legendLabel":"Six", "magnitude":8}, 
      {"legendLabel":"Seven", "magnitude":30}];
    
    var vis = d3.select("body")
      .append("svg:svg") //create the SVG element inside the <body>
        .data([dataSet]) //associate our data with the document
        .attr("width", canvasWidth) //set the width of the canvas
        .attr("height", canvasHeight) //set the height of the canvas
        .append("svg:g") //make a group to hold our pie chart
          .attr("transform", "translate(" + 1.5*outerRadius + "," + 1.5*outerRadius + ")") // relocate center of pie to 'outerRadius,outerRadius'

    // This will create <path> elements for us using arc data...
    var arc = d3.svg.arc()
      .outerRadius(outerRadius);

    var pie = d3.layout.pie() //this will create arc data for us given a list of values
      .value(function(d) { return d.magnitude; }) // Binding each value to the pie
      .sort( function(d) { return null; } );

    // Select all <g> elements with class slice (there aren't any yet)
    var arcs = vis.selectAll("g.slice")
      // Associate the generated pie data (an array of arcs, each having startAngle,
      // endAngle and value properties) 
      .data(pie)
      // This will create <g> elements for every "extra" data element that should be associated
      // with a selection. The result is creating a <g> for every object in the data array
      .enter()
      // Create a group to hold each slice (we will have a <path> and a <text>
      // element associated with each slice)
      .append("svg:g")
      .attr("class", "slice")    //allow us to style things in the slices (like text)
    .on('click',function(d,i){
       d3.select(this)
        .transition()
        .duration(500)
        .attr("transform",function(d){
            if (!d.data._expanded){
                d.data._expanded = true;
                var a = d.startAngle + (d.endAngle - d.startAngle)/2 - Math.PI/2;
                var x = Math.cos(a) * 20;
                var y = Math.sin(a) * 20;
                return 'translate(' + x + ',' + y + ')';                
            } else {
                d.data._expanded = false;
                return 'translate(0,0)';                
            }
        }); 
    });

    arcs.append("svg:path")
      //set the color for each slice to be chosen from the color function defined above
      .attr("fill", function(d, i) { return color(i); } )
      //this creates the actual SVG path using the associated data (pie) with the arc drawing function
      .attr("d", arc);

    // Add a legendLabel to each arc slice...
    arcs.append("svg:text")
      .attr("transform", function(d) { //set the label's origin to the center of the arc
        //we have to make sure to set these before calling arc.centroid
        d.outerRadius = outerRadius + 50; // Set Outer Coordinate
        d.innerRadius = outerRadius + 45; // Set Inner Coordinate
        return "translate(" + arc.centroid(d) + ")";
      })
      .attr("text-anchor", "middle") //center the text on it's origin
      .style("fill", "Purple")
      .style("font", "bold 12px Arial")
      .text(function(d, i) { return dataSet[i].legendLabel; }); //get the label from our original data array

    // Add a magnitude value to the larger arcs, translated to the arc centroid and rotated.
    arcs.filter(function(d) { return d.endAngle - d.startAngle > .2; }).append("svg:text")
      .attr("dy", ".35em")
      .attr("text-anchor", "middle")
      //.attr("transform", function(d) { return "translate(" + arc.centroid(d) + ")rotate(" + angle(d) + ")"; })
      .attr("transform", function(d) { //set the label's origin to the center of the arc
        //we have to make sure to set these before calling arc.centroid
        d.outerRadius = outerRadius; // Set Outer Coordinate
        d.innerRadius = outerRadius/2; // Set Inner Coordinate
        return "translate(" + arc.centroid(d) + ")rotate(" + angle(d) + ")";
      })
      .style("fill", "White")
      .style("font", "bold 12px Arial")
      .text(function(d) { return d.data.magnitude; });

    // Computes the angle of an arc, converting from radians to degrees.
    function angle(d) {
      var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;
      return a > 90 ? a - 180 : a;
    }
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>