图例在d3响应式图表中未正确对齐

时间:2016-06-21 06:43:49

标签: d3.js pie-chart

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-type" content="text/html; charset=utf-8">
    <title>Testing Pie Chart</title>
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
     <style type="text/css">

     #container {
        margin: 20px;
      }

     #chart {  
        position: absolute;  
        background-color: #eee;                                          
      }
      #chart legend{  
        position: absolute;  
        margin: 100px;                                        
      }                                                                 
      .tooltip {                                                        
        background: #eee;                                               
        box-shadow: 0 0 5px #999999;                                    
        color: #900C3F;                                                    
        display: inline-block;                                                  
        font-size: 12px;                                                
        left: 600px;                                                    
        padding: 10px;                                                  
        position: absolute;                                             
        text-align: center;                                             
        top: 95px;                                                      
        width: 150px;                                                    
        z-index: 10;  
        opacity: 1;                                                 
    }                                                                 
    rect {
       stroke-width: 2;
    }
    path {
        stroke: #ffffff;
        stroke-width: 0.5;
    }
    div.tooltip {
    position: absolute;
    z-index: 999;
    padding: 10px;
    background: #f4f4f4;
    border: 0px;
    border-radius: 3px;
    pointer-events: none;
    font-size: 11px;
    color:  #080808;
    line-height: 16px;
    border: 1px solid #d4d4d4;
    }

     </style>
      </head>
  <body>

    <div id="container">
    <svg id="chart" width="600" height="300" viewBox="0 0 600 300" perserveAspectRatio="xMinYMid">
    <div id="toolTip" class="tooltip" style="opacity: 0;"></div>
    <script type="text/javascript">

var div = d3.select("#toolTip");

var data = [
      {"IP":"192.168.12.1", "count":20}, 
      {"IP":"76.09.45.34", "count":40}, 
      {"IP":"34.91.23.76", "count":80},
      {"IP":"192.168.19.32", "count":16}, 
      {"IP":"192.168.10.89", "count":50}, 
      {"IP":"192.178.34.07", "count":18},
      {"IP":"192.168.12.98", "count":30}];

var width = 300,
    height = 300;
var margin = {top: 15, right: 15, bottom: 20, left: 40},
    radius = Math.min(width, height) / 2 - 10;
var legendRectSize = 18,
    legendSpacing = 4;
            

        var color = d3.scale.category20b();

        var arc = d3.svg.arc()
            .outerRadius(radius);
          
          var arcOver = d3.svg.arc()
                .outerRadius(radius + 5);

        var pie = d3.layout.pie()
            .sort(null)
            .value(function(d) { return d.count; });

        var labelArc = d3.svg.arc()
            .outerRadius(radius - 40)
            .innerRadius(radius - 40);
          
        var svg = d3.select("#chart").append("svg")
            .datum(data)
            .attr("width", width)
            .attr("height", height)
            .append("g")
            .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

        var arcs = svg.selectAll(".arc")
            .data(pie)
            .enter().append("g")
            .attr("class", "arc");
          
         var arcs2 = svg.selectAll(".arc2")
            .data(pie)
            .enter().append("g")
            .attr("class", "arc2");

          
        arcs.append("path")
            .attr("fill", function(d, i) { return color(i); })
            .on("mouseover", function(d) {
                var htmlMsg="";
                div.transition()        
                    .style("opacity",0.9);
                var total = d3.sum(data.map(function(d) {                   
                    return d.count;                                           
                })); 
                var percent = Math.round(1000 * d.data.count / total) / 10;         
                div.html(
                 "IP :"+ d.data.IP +""+"<br/>"+
                 "Count : " +  d.data.count +"<br/>" + 
                 "Percent: " + percent + '%'+ htmlMsg)
                .style("left",  (d3.event.pageX) + "px")
                .style("top",  (d3.event.pageY) + "px");    

                svg.selectAll("path").sort(function (a, b) { 
                    if (a != d) return -1;               
                    else return 1;                             
                });
          
                var endAngle = d.endAngle + 0.1;
                var startAngle = d.startAngle - 0.1;
                var arcOver = d3.svg.arc()
                    .outerRadius(radius + 10).endAngle(endAngle).startAngle(startAngle);
                        d3.select(this)
                        .attr("stroke","white")
                        .transition()
                        .ease("bounce")
                        .duration(1000)
                        .attr("d", arcOver)             
                        .attr("stroke-width",6);
                    })

            .on("mouseout", function(d) {
                div.transition()        
                .duration(500)      
                .style("opacity", 0); 
                    d3.select(this).transition()            
                       .attr("d", arc)
                       .attr("stroke","none");
                })
                .transition()
                .ease("bounce")
                .duration(2000)
                .attrTween("d", tweenPie);

        function tweenPie(b) {
          b.innerRadius = 0;
          var i = d3.interpolate({startAngle: 0, endAngle: 0}, b);
          return function(t) { return arc(i(t)); };
        }

        var k=0;
        arcs2.append("text")
        .transition()
            .ease("elastic")
            .duration(2000)
            .delay(function (d, i) {
                return i * 250;
            })
              .attr("x","6")
              .attr("dy", ".35em")
              .text(function(d) { if(d.data.count >0){ k = k+1; return d.data.count;} })
              .attr("transform", function(d) { if (k >1){return "translate(" + labelArc.centroid(d) + ") rotate(" + angle(d) + ")";} else{return "rotate(-360)";} })
              .attr("font-size", "10px");
        

        function type(d) {
          d.count = +d.count;
          return d;
        }
        function angle(d) {
              var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;
              return a > 90 ? a - 180 : a;
        }

 var legend = d3.select("#chart")
    .append("svg")
    .attr("class", "legend")
    .attr("width", radius+50)
    .attr("height", radius * 2)
    .selectAll("g")
    .data(color.domain())
    .enter()
    .append("g")
    .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });

 legend.append('rect')
    .attr('width', legendRectSize)
    .attr('height', legendRectSize)                                   
   .style('fill', color)
   .style('stroke', color);
  
  legend.append('text')
    .attr('x', legendRectSize + legendSpacing)
    .attr('y', legendRectSize - legendSpacing)
    .data(data)
    .text(function(d,i) { return d.IP; });

  </script>   
  </svg>
  </div>

  <script type="text/javascript">
var chart = $("#chart"),
    aspect = chart.width() / chart.height(),
    container = chart.parent();
$(window).on("resize", function() {
    var targetWidth = container.width();
    chart.attr("width", targetWidth);
    chart.attr("height", Math.round(targetWidth / aspect));
}).trigger("resize");
</script>

    </script>
  </body>
 </html>

你好,我是D3.js的新手。在构建响应式饼图时,我遇到了问题。图表响应时也附加了工具提示。但是当我尝试将图例附加到图表时,图例与图表重叠。请帮我。我被卡住了。如何将图例放在饼图旁边。这是我到目前为止尝试过的代码。 提前感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

这可以通过3种方式解决:

  1. 图表宽度

    这里,饼图对于给定的尺寸来说太大了。因此,传说重叠。您可以尝试将width: 300更改为width: 700

  2. 圆的半径

    如果无法更改宽度,则可以减小饼图的半径。目前,它选择最小宽度/高度并除以2减去10作为保证金。 radius = Math.min(width, height) / 2您还可以指定radius = Math.min(width, height) / 2 - 50以进一步按像素缩小半径。

  3. 转变中心

    或者您也可以进一步向右移动饼图的中心。目前,它位于尺寸的一半。 .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")。你可以说它是宽度的3/4和高度的40%.attr("transform", "translate(" + width * 3 / 4 + "," + height * 2 / 5 + ")")

  4. 我已经在你的代码段中使用了所有这三种方式:

    &#13;
    &#13;
    <!DOCTYPE html>
    <html>
      <head>
        <meta http-equiv="Content-type" content="text/html; charset=utf-8">
        <title>Testing Pie Chart</title>
    <script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
    <script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
         <style type="text/css">
    
         #container {
            margin: 20px;
          }
    
         #chart {  
            position: absolute;  
            background-color: #eee;                                          
          }
          #chart legend{  
            position: absolute;  
            margin: 100px;                                        
          }                                                                 
          .tooltip {                                                        
            background: #eee;                                               
            box-shadow: 0 0 5px #999999;                                    
            color: #900C3F;                                                    
            display: inline-block;                                                  
            font-size: 12px;                                                
            left: 600px;                                                    
            padding: 10px;                                                  
            position: absolute;                                             
            text-align: center;                                             
            top: 95px;                                                      
            width: 150px;                                                    
            z-index: 10;  
            opacity: 1;                                                 
        }                                                                 
        rect {
           stroke-width: 2;
        }
        path {
            stroke: #ffffff;
            stroke-width: 0.5;
        }
        div.tooltip {
        position: absolute;
        z-index: 999;
        padding: 10px;
        background: #f4f4f4;
        border: 0px;
        border-radius: 3px;
        pointer-events: none;
        font-size: 11px;
        color:  #080808;
        line-height: 16px;
        border: 1px solid #d4d4d4;
        }
    
         </style>
          </head>
      <body>
    
        <div id="container">
        <svg id="chart" width="600" height="300" viewBox="0 0 600 300" perserveAspectRatio="xMinYMid">
        <div id="toolTip" class="tooltip" style="opacity: 0;"></div>
        <script type="text/javascript">
    
    var div = d3.select("#toolTip");
    
    var data = [
          {"IP":"192.168.12.1", "count":20}, 
          {"IP":"76.09.45.34", "count":40}, 
          {"IP":"34.91.23.76", "count":80},
          {"IP":"192.168.19.32", "count":16}, 
          {"IP":"192.168.10.89", "count":50}, 
          {"IP":"192.178.34.07", "count":18},
          {"IP":"192.168.12.98", "count":30}];
    
    var width = 400,
        height = 300;
    var margin = {top: 15, right: 15, bottom: 20, left: 40},
        radius = Math.min(width, height) / 2 - 50;
    var legendRectSize = 18,
        legendSpacing = 4;
                
    
            var color = d3.scale.category20b();
    
            var arc = d3.svg.arc()
                .outerRadius(radius);
              
              var arcOver = d3.svg.arc()
                    .outerRadius(radius + 5);
    
            var pie = d3.layout.pie()
                .sort(null)
                .value(function(d) { return d.count; });
    
            var labelArc = d3.svg.arc()
                .outerRadius(radius - 40)
                .innerRadius(radius - 40);
              
            var svg = d3.select("#chart").append("svg")
                .datum(data)
                .attr("width", width)
                .attr("height", height)
                .append("g")
                .attr("transform", "translate(" + width * 3 / 4  + "," + height * 2/ 5 + ")");
    
            var arcs = svg.selectAll(".arc")
                .data(pie)
                .enter().append("g")
                .attr("class", "arc");
              
             var arcs2 = svg.selectAll(".arc2")
                .data(pie)
                .enter().append("g")
                .attr("class", "arc2");
    
              
            arcs.append("path")
                .attr("fill", function(d, i) { return color(i); })
                .on("mouseover", function(d) {
                    var htmlMsg="";
                    div.transition()        
                        .style("opacity",0.9);
                    var total = d3.sum(data.map(function(d) {                   
                        return d.count;                                           
                    })); 
                    var percent = Math.round(1000 * d.data.count / total) / 10;         
                    div.html(
                     "IP :"+ d.data.IP +""+"<br/>"+
                     "Count : " +  d.data.count +"<br/>" + 
                     "Percent: " + percent + '%'+ htmlMsg)
                    .style("left",  (d3.event.pageX) + "px")
                    .style("top",  (d3.event.pageY) + "px");    
    
                    svg.selectAll("path").sort(function (a, b) { 
                        if (a != d) return -1;               
                        else return 1;                             
                    });
              
                    var endAngle = d.endAngle + 0.1;
                    var startAngle = d.startAngle - 0.1;
                    var arcOver = d3.svg.arc()
                        .outerRadius(radius + 10).endAngle(endAngle).startAngle(startAngle);
                            d3.select(this)
                            .attr("stroke","white")
                            .transition()
                            .ease("bounce")
                            .duration(1000)
                            .attr("d", arcOver)             
                            .attr("stroke-width",6);
                        })
    
                .on("mouseout", function(d) {
                    div.transition()        
                    .duration(500)      
                    .style("opacity", 0); 
                        d3.select(this).transition()            
                           .attr("d", arc)
                           .attr("stroke","none");
                    })
                    .transition()
                    .ease("bounce")
                    .duration(2000)
                    .attrTween("d", tweenPie);
    
            function tweenPie(b) {
              b.innerRadius = 0;
              var i = d3.interpolate({startAngle: 0, endAngle: 0}, b);
              return function(t) { return arc(i(t)); };
            }
    
            var k=0;
            arcs2.append("text")
            .transition()
                .ease("elastic")
                .duration(2000)
                .delay(function (d, i) {
                    return i * 250;
                })
                  .attr("x","6")
                  .attr("dy", ".35em")
                  .text(function(d) { if(d.data.count >0){ k = k+1; return d.data.count;} })
                  .attr("transform", function(d) { if (k >1){return "translate(" + labelArc.centroid(d) + ") rotate(" + angle(d) + ")";} else{return "rotate(-360)";} })
                  .attr("font-size", "10px");
            
    
            function type(d) {
              d.count = +d.count;
              return d;
            }
            function angle(d) {
                  var a = (d.startAngle + d.endAngle) * 90 / Math.PI - 90;
                  return a > 90 ? a - 180 : a;
            }
    
     var legend = d3.select("#chart")
        .append("svg")
        .attr("class", "legend")
        .attr("width", radius+50)
        .attr("height", radius * 2)
        .selectAll("g")
        .data(color.domain())
        .enter()
        .append("g")
        .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
    
     legend.append('rect')
        .attr('width', legendRectSize)
        .attr('height', legendRectSize)                                   
       .style('fill', color)
       .style('stroke', color);
      
      legend.append('text')
        .attr('x', legendRectSize + legendSpacing)
        .attr('y', legendRectSize - legendSpacing)
        .data(data)
        .text(function(d,i) { return d.IP; });
    
      </script>   
      </svg>
      </div>
    
      <script type="text/javascript">
    var chart = $("#chart"),
        aspect = chart.width() / chart.height(),
        container = chart.parent();
    $(window).on("resize", function() {
        var targetWidth = container.width();
        chart.attr("width", targetWidth);
        chart.attr("height", Math.round(targetWidth / aspect));
    }).trigger("resize");
    </script>
    
        </script>
      </body>
     </html>
    &#13;
    &#13;
    &#13;