在d3.js中,每一级都有多个元素的金字塔,我必须使用d3.js从数据中创建一个金字塔可视化。

问题描述 投票:0回答:1

我必须使用d3.js从数据中创建一个金字塔可视化。附上一个示例视图。有2个挑战,我希望得到帮助。

  1. 我知道如何创建一个金字塔,看下面给出的例子,但我不明白,我如何能添加多个元素(图像中显示的值,如A,B,C等)在每一级http:/bl.ocks.orgronakrb73e9204a66e2a9c1fee8。

  2. 我想为最低层的一些元素附加一个树状结构。

我不能用树状结构代替金字塔,因为每层的元素之间没有父子关系。

enter image description here

示例演示数据。

const data = [
    { Name: "G", level: 1},
    { Name: "F", level: 2},
    { Name: "DE", level: 2},
    { Name: "C", level: 3},
    { Name: "B", level: 3},
    { Name: "A", level: 3, team: [1,2,3]}
]
javascript d3.js data-visualization visualization
1个回答
1
投票

这里有一种方法来做 - 这是第一次 粗通。如果你说是沿着正确的方向,我可以改进和完善。

(我需要改进间距的大小,我还需要把队员加到字母A上,还需要大体清理一下等等)

更新时间:20年6月11日 - 清理了间距,在字母周围添加了方框,在数字周围添加了圆圈。

var width = 700,
      height = 450,
      radius = Math.min(width, height) / 2;

  var color = d3.scale.ordinal()
      .range(["#255aee","#3a6fff","#4f84ff","rgb(101,154,302)","rgb(122,175,323)", "rgb(144,197,345)", "rgb(165,218,366)"]);

  var svg = d3.select("body").append("svg")
      .attr("width", width)
      .attr("height", height)
      .append("g")
  //*    
  const data = [
    { Name: "G", level: 1},
    { Name: "F", level: 2},
    { Name: "DE", level: 2},
    { Name: "C", level: 3},
    { Name: "B", level: 3},
    { Name: "A", level: 3, team: [1,2,3]}
  ];
  //*/
  const grouped = Object.values(data.reduce((aggObj, item) => {
    
    if (!aggObj[item.level]){
      aggObj[item.level] = {level: item.level, names: []};
    }
    aggObj[item.level].names.push({name: item.Name, team: item.team});
    return aggObj;
  }, {}));
  
  //console.log(grouped);
  
      var pyramid = d3.pyramid()
          .size([width,height])
          .value(function(d) { return d.level; });

      var line = d3.svg.line()
          .interpolate('linear-closed')
          .x(function(d,i) { return d.x; })
          .y(function(d,i) { return d.y; });

      var g = svg.selectAll(".pyramid-group")
          .data(pyramid(grouped)) //swap for grouped data
          .enter().append("g")
          .attr("class", "pyramid-group");

      g.append("path")
          .attr("d", function (d){ return line(d.coordinates); })
          .style("fill", function(d) { return color(d.level); });

      var textBoxes = g.selectAll(".textBoxes")
          .data((d) => {
            const helperObj = {};
            helperObj.coordinates = d.coordinates;
            helperObj.level = d.level;
            const len = d.names.length;
            helperObj.len = d.names.length;
            if(d.coordinates.length === 4) {
                const left = d.coordinates[0].x;
                const right = d.coordinates[3].x;
                const topLeft = d.coordinates[1].x;
                const topRight = d.coordinates[2].x;
                const start = left + ((topLeft - left) / 2);
                const end = right - ((right - topRight) / 2);
                const sep = (end - start) / len;
                helperObj.start = start;
                helperObj.end = end;
                helperObj.sep = sep;
                const yCenter = (((d.coordinates[0].y-d.coordinates[1].y)/2)+d.coordinates[1].y) + 5;
                helperObj.yCenter = yCenter;
                helperObj.yDiff = (d.coordinates[0].y-d.coordinates[1].y);
            } else {
                const left = d.coordinates[1].x;
                const right = d.coordinates[2].x;
                const start = left + ((right - left) / 4);
                const end = right - ((right - left) / 4);
                const sep = (end - start) / len;
                helperObj.start = start;
                helperObj.end = end;
                helperObj.sep = sep;
                helperObj.yCenter = (d.coordinates[0].y + d.coordinates[1].y)/2 + 10;
                helperObj.yDiff = (d.coordinates[1].y-d.coordinates[0].y) * 0.9;
            } 
                  
            return d.names.map((e,i) => {
              const name = e.name;
              const team = e.team || [];
              const teamLen = team.length;
              return {...helperObj, i, name, team, teamLen};
            })
          })
          .enter().append("g");
          
      textBoxes.append("rect")
          .attr({
              "y": function (d,i) {
                  //console.log(d)
                  return d.yCenter - (d.yDiff/8);
              },
              "x": function (d,i) {
                  return d.start + ((i+0.05) * d.sep);
              },
              "width": function (d,i) {
                  return d.sep * 0.9;         
              },
              "height": function (d,i) {
                  return (d.yDiff/8) * 3;         
              },
              "fill": function (d,i) {
                  return "#e0f4ff";         
              },
              "rx": function (d,i) {
                  return d.sep * 0.1;   
              }
          });
          
      textBoxes.append("text")
          .attr({
              "y": function (d,i) {
                  //console.log(d)
                  return d.yCenter;
              },
              "x": function (d,i) {
                  return d.start + ((i+0.5) * d.sep);
              }
          })          
          .style("text-anchor", "middle")
          .style("alignment-baseline", "hanging")
          .style("font-size", "x-large")
          .text(function(d) { return d.name; });
          
      var teamMembers = textBoxes.selectAll(".teamMembers")
          .data((d) => {
            const itemCopy = {...d};
            const teamCopy = [...d.team];
            delete itemCopy.team;
            return d.team.map(e => ({...itemCopy, teamMember: e}));
          });
      teamMembers.enter().append("line")
          .attr({
              "y1": function (d,i) {
                  //console.log(d)
                  return d.yCenter + (d.yDiff/3);
              },
              "x1": function (d,i) {
                  return d.start + ((d.i+0.15) * d.sep) + ((i+0.5) * ((0.7*d.sep)/d.teamLen));
              },
              "y2": function (d,i) {
                  //console.log(d)
                  return d.yCenter + (d.yDiff/6);
              },
              "x2": function (d,i) {
                  return d.start + ((d.i+0.15) * d.sep) + (0.5 * (0.7*d.sep));
              },
              "stroke": function (d,i) {
                  //console.log(d)
                  return "black";
              },
              "stroke-width": function (d,i) {
                  return "2";
              }
          });    
      teamMembers.enter().append("circle")
          .attr({
              "cy": function (d,i) {
                  //console.log(d)
                  return d.yCenter + (d.yDiff/3);
              },
              "cx": function (d,i) {
                  return d.start + ((d.i+0.15) * d.sep) + ((i+0.5) * ((0.7*d.sep)/d.teamLen));
              },
              "r": function (d,i) {
                  return d.sep * 0.05;
              }
          });
      teamMembers.enter().append("text")
          .attr({
              "y": function (d,i) {
                  //console.log(d)
                  return d.yCenter + (d.yDiff/3);
              },
              "x": function (d,i) {
                  return d.start + ((d.i+0.15) * d.sep) + ((i+0.5) * ((0.7*d.sep)/d.teamLen));
              },
              "fill": function (d,i) {
                  return "white";
              }
          })
          .style("text-anchor", "middle")
          .style("alignment-baseline", "middle")
          .style("font-size", "large")
          .text(function(d) { return d.teamMember; });

      d3.select("body").append("table")
          .attr({
              "id" : "footer",
              "width": width + "px"
          })

      d3.select("body #footer").append("tr")
          .attr({
              "class" : "PykCharts-credits",
              "id" : "credit-datasource"
          })
          .append("td")
          .style("text-align","left")
          .html("<span style='pointer-events:none;'>Credits: </span><a href='http://pykcharts.com' target='_blank'>"+  "Pykcharts" +"</a>");
<html>
    <head>
        <style>
            body {
                font: 10px sans-serif;
                }

            .arc path {
                stroke: #fff;
            }

        </style>
    </head>
    <body>
        <script src="https://d3js.org/d3.v3.min.js"></script>
        <script src="https://s3-ap-southeast-1.amazonaws.com/charts.pykih.com/gists/pyramid.js"></script>        
    </body>
</html>

输出。

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.