javascript - 如何在 d3 饼图中添加漂亮的图例

标签 javascript d3.js

我的饼图工作正常,但我想添加一个像这样的漂亮图例(用 mspaint 制作)

enter image description here

但不能让它工作......

这是我的饼图代码(没有图例部分):

<!DOCTYPE html>
<html>

<head>
  <script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>

<body>
  <script>
    var newData = [{
        count: 1,
        emote: "OneTwoThree"
      }, {
        count: 1,
        emote: "FourFiveSix"
      }, {
        count: 1,
        emote: "SevenEightNine"
      }, {
        count: 15,
        emote: "TenElevenTwelve"
      },

    ]

    // Define size & radius of donut pie chart
    var width = 450,
      height = 800,
      radius = Math.min(width, height) / 2;

    // Define arc colours
    var colour = d3.scale.category20();

    // Define arc ranges
    var arcText = d3.scale.ordinal()
      .rangeRoundBands([0, width], .1, .3);

    // Determine size of arcs
    var arc = d3.svg.arc()
      .innerRadius(radius - 130)
      .outerRadius(radius - 10);

    // Create the donut pie chart layout
    var pie = d3.layout.pie()
      .value(function(d) {
        return d.count;
      })
      .sort(null);

    // Append SVG attributes and append g to the SVG
    var mySvg = d3.select('body').append("svg")
      .attr("width", width)
      .attr("height", height);

    var svg = mySvg
      .append("g")
      .attr("transform", "translate(" + radius + "," + radius + ")");

    var svgText = mySvg
      .append("g")
      .attr("transform", "translate(" + radius + "," + radius + ")");

    // Define inner circle
    svg.append("circle")
      .attr("cx", 0)
      .attr("cy", 0)
      .attr("r", 100)
      .attr("fill", "#fff");

    // Calculate SVG paths and fill in the colours
    var g = svg.selectAll(".arc")
      .data(pie(newData))
      .enter().append("g")
      .attr("class", "arc");

    // Append the path to each g
    g.append("path")
      .attr("d", arc)
      //.attr("data-legend", function(d, i){ return parseInt(newData[i].count) + ' ' + newData[i].emote; })
      .attr("fill", function(d, i) {
        return colour(i);
      });

    var textG = svg.selectAll(".labels")
      .data(pie(newData))
      .enter().append("g")
      .attr("class", "labels");

    // Append text labels to each arc
    textG.append("text")
      .attr("transform", function(d) {
        return "translate(" + arc.centroid(d) + ")";
      })
      .attr("dy", ".35em")
      .style("text-anchor", "middle")
      .attr("fill", "#fff")
      .text(function(d, i) {
        return d.data.count > 0 ? d.data.emote : '';
      });
  </script>
</body>

</html>

最佳答案

我很惊讶没有更多的这种“股票”例子。

这是一个与您的数据看起来不错的快速图例:

// again rebind for legend
var legendG = mySvg.selectAll(".legend") // note appending it to mySvg and not svg to make positioning easier
  .data(pie(newData))
  .enter().append("g")
  .attr("transform", function(d,i){
    return "translate(" + (width - 110) + "," + (i * 15 + 20) + ")"; // place each legend on the right and bump each one down 15 pixels
  })
  .attr("class", "legend");   

legendG.append("rect") // make a matching color rect
  .attr("width", 10)
  .attr("height", 10)
  .attr("fill", function(d, i) {
    return colour(i);
  });

legendG.append("text") // add the text
  .text(function(d){
    return d.value + "  " + d.data.emote;
  })
  .style("font-size", 12)
  .attr("y", 10)
  .attr("x", 11);

完整示例:

<!DOCTYPE html>
<html>

<head>
  <script data-require="d3@3.5.3" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script>
</head>

<body>
  <script>
    var newData = [{
        count: 1,
        emote: "OneTwoThree"
      }, {
        count: 1,
        emote: "FourFiveSix"
      }, {
        count: 1,
        emote: "SevenEightNine"
      }, {
        count: 15,
        emote: "TenElevenTwelve"
      },

    ]

    // Define size & radius of donut pie chart
    var width = 450,
      height = 800,
      radius = Math.min(width, height) / 2.5;

    // Define arc colours
    var colour = d3.scale.category20();

    // Define arc ranges
    var arcText = d3.scale.ordinal()
      .rangeRoundBands([0, width], .1, .3);

    // Determine size of arcs
    var arc = d3.svg.arc()
      .innerRadius(radius - 130)
      .outerRadius(radius - 10);

    // Create the donut pie chart layout
    var pie = d3.layout.pie()
      .value(function(d) {
        return d.count;
      })
      .sort(null);

    // Append SVG attributes and append g to the SVG
    var mySvg = d3.select('body').append("svg")
      .attr("width", width)
      .attr("height", height);

    var svg = mySvg
      .append("g")
      .attr("transform", "translate(" + radius + "," + radius + ")");

    var svgText = mySvg
      .append("g")
      .attr("transform", "translate(" + radius + "," + radius + ")");

    // Define inner circle
    svg.append("circle")
      .attr("cx", 0)
      .attr("cy", 0)
      .attr("r", 100)
      .attr("fill", "#fff");

    // Calculate SVG paths and fill in the colours
    var g = svg.selectAll(".arc")
      .data(pie(newData))
      .enter().append("g")
      .attr("class", "arc");

    // Append the path to each g
    g.append("path")
      .attr("d", arc)
      //.attr("data-legend", function(d, i){ return parseInt(newData[i].count) + ' ' + newData[i].emote; })
      .attr("fill", function(d, i) {
        return colour(i);
      });

    var textG = svg.selectAll(".labels")
      .data(pie(newData))
      .enter().append("g")
      .attr("class", "labels");

    // Append text labels to each arc
    textG.append("text")
      .attr("transform", function(d) {
        return "translate(" + arc.centroid(d) + ")";
      })
      .attr("dy", ".35em")
      .style("text-anchor", "middle")
      .attr("fill", "#fff")
      .text(function(d, i) {
        return d.data.count > 0 ? d.data.emote : '';
      });
    
    var legendG = mySvg.selectAll(".legend")
      .data(pie(newData))
      .enter().append("g")
      .attr("transform", function(d,i){
        return "translate(" + (width - 110) + "," + (i * 15 + 20) + ")";
      })
      .attr("class", "legend");   
    
    legendG.append("rect")
      .attr("width", 10)
      .attr("height", 10)
      .attr("fill", function(d, i) {
        return colour(i);
      });
    
    legendG.append("text")
      .text(function(d){
        return d.value + "  " + d.data.emote;
      })
      .style("font-size", 12)
      .attr("y", 10)
      .attr("x", 11);
    
    
  </script>
</body>

</html>

关于javascript - 如何在 d3 饼图中添加漂亮的图例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32298837/

相关文章:

javascript - 无法对 D3 v4 中的对象使用 attr

javascript - d3 在鼠标悬停时过滤数据后从选择中提取值

D3.js 动态更新 Treemap

javascript - Three.js 带顶点的 RGB 立方体

javascript - 尝试在图表上绘制虚线

javascript - 根据 'more detail' 字段对有条件启用的 'parent' 表单字段进行分组的优雅方法

ajax - d3.js 按需数据加载获取树的下一个节点

javascript - 在 HTML/JS/JQuery 中屏蔽单词

javascript - axios GET 请求有效,但无法将结果内容分配给变量

javascript - 我如何使这个内环更厚 - 换句话说,使内部白色圆圈的半径更小