D3.js如何使用嵌入非分层数据的分层布局

D3.js how to use hierarchical layouts with embedded non hierarchical data

本文关键字:分层 数据 布局 js 何使用 D3      更新时间:2023-09-26

我试图用嵌入的数据调整mike bostock的树布局示例http://bl.ocks.org/mbostock/4339083.嵌入的数据应该是一个非分层的。csv文件的副本:

getData2 ()从"pre"标签获取数据并嵌套它。但由于某些原因,它不起作用。

getData3()也不工作,因为某些原因,我使用一个变量与非嵌套数组,然后嵌套它。

我如何改变getData2()和getData3()方法使其工作?

这是我的html文件:
<!DOCTYPE html>
<html>
   <pre id="csvdata">
   Year,Make,Model,Length
    1997,BMW,E350,2.34
    1997,BMW,E350,2.34
    2000,Mercury,Cougar,2.38
    </pre>
  <head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
    <link type="text/css" rel="stylesheet" href="style.css"/>
    <script type="text/javascript" src="../lib/d3.min.js"></script>
    <!--<script type="text/javascript" src="d3/d3.layout.js"></script> -->
    <style type="text/css">
    .node circle {
      cursor: pointer;
      fill: #fff;
      stroke: steelblue;
      stroke-width: 1.5px;
    }
    .node text {
      font-size: 11px;
    }
    path.link {
      fill: none;
      stroke: #ccc;
      stroke-width: 1.5px;
    }
    #csvdata {
        display: none;
    }
    </style>
  </head>
  <body>
    <div id="body">
      <div id="footer">
        d3.layout.tree
        <div class="hint">click or option-click to expand or collapse</div>
      </div>
    </div>
    <script type="text/javascript">
    var margin = {top: 20, right: 120, bottom: 20, left: 120},
    width = 960 - margin.right - margin.left,
    height = 800 - margin.top - margin.bottom;
var i = 0,
    duration = 750,
    root;
var tree = d3.layout.tree()
    .size([height, width]);
var diagonal = d3.svg.diagonal()
    .projection(function(d) { return [d.y, d.x]; });
var svg = d3.select("body").append("svg")
    .attr("width", width + margin.right + margin.left)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
    // root = getData();  // that works
    // root = getData2(); // that doesn't work
  root = getData3(); // that doesn't work either
  console.log(root);
  root.x0 = height / 2;
  root.y0 = 0;
  function collapse(d) {
    if (d.children) {
      d._children = d.children;
      d._children.forEach(collapse);
      d.children = null;
    }
  }
  root.children.forEach(collapse);
  update(root);

d3.select(self.frameElement).style("height", "800px");
function update(source) {
  // Compute the new tree layout.
  var nodes = tree.nodes(root).reverse(),
      links = tree.links(nodes);
  // Normalize for fixed-depth.
  nodes.forEach(function(d) { d.y = d.depth * 180; });
  // Update the nodes…
  var node = svg.selectAll("g.node")
      .data(nodes, function(d) { return d.id || (d.id = ++i); });
  // Enter any new nodes at the parent's previous position.
  var nodeEnter = node.enter().append("g")
      .attr("class", "node")
      .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
      .on("click", click);
  nodeEnter.append("circle")
      .attr("r", 1e-6)
      .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
  nodeEnter.append("text")
      .attr("x", function(d) { return d.children || d._children ? -10 : 10; })
      .attr("dy", ".35em")
      .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
      .text(function(d) { return d.name; })
      .style("fill-opacity", 1e-6);
  // Transition nodes to their new position.
  var nodeUpdate = node.transition()
      .duration(duration)
      .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
  nodeUpdate.select("circle")
      .attr("r", 4.5)
      .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
  nodeUpdate.select("text")
      .style("fill-opacity", 1);
  // Transition exiting nodes to the parent's new position.
  var nodeExit = node.exit().transition()
      .duration(duration)
      .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
      .remove();
  nodeExit.select("circle")
      .attr("r", 1e-6);
  nodeExit.select("text")
      .style("fill-opacity", 1e-6);
  // Update the links…
  var link = svg.selectAll("path.link")
      .data(links, function(d) { return d.target.id; });
  // Enter any new links at the parent's previous position.
  link.enter().insert("path", "g")
      .attr("class", "link")
      .attr("d", function(d) {
        var o = {x: source.x0, y: source.y0};
        return diagonal({source: o, target: o});
      });
  // Transition links to their new position.
  link.transition()
      .duration(duration)
      .attr("d", diagonal);
  // Transition exiting nodes to the parent's new position.
  link.exit().transition()
      .duration(duration)
      .attr("d", function(d) {
        var o = {x: source.x, y: source.y};
        return diagonal({source: o, target: o});
      })
      .remove();
  // Stash the old positions for transition.
  nodes.forEach(function(d) {
    d.x0 = d.x;
    d.y0 = d.y;
  });
}
// Toggle children on click.
function click(d) {
  if (d.children) {
    d._children = d.children;
    d.children = null;
  } else {
    d.children = d._children;
    d._children = null;
  }
  update(d);
}
function getData2() {
    csv_data = d3.select("#csvdata");
    var nested_data = d3.nest()
        .key(function(d) { return d.Make; })
        .entries(csv_data);
    return nested_data; 
}
function getData3() {
    var yields = [{yield: 27.00, variety: "Manchuria", year: 1931, site: "University Farm"},
              {yield: 48.87, variety: "Manchuria", year: 1931, site: "Waseca"},
              {yield: 27.43, variety: "Manchuria", year: 1931, site: "Morris"}];
    var nest = d3.nest()
        .key(function(d) { return d.year; })
        .key(function(d) { return d.variety; })
        .entries(yields);
    return nest;        
}
function getData() {
return{
        "name": "flare",
            "children": [{
            "name": "analytics",
                "children": [{
                "name": "cluster",
                    "children": [{
                    "name": "AgglomerativeCluster",
                    "size": 3938
                }, {
                    "name": "CommunityStructure",
                    "size": 3812
                }, {
                    "name": "HierarchicalCluster",
                    "size": 6714
                }, {
                    "name": "MergeEdge",
                    "size": 743
                }]
            }, {
                "name": "graph",
                    "children": [{
                    "name": "BetweennessCentrality",
                    "size": 3534
                }, {
                    "name": "LinkDistance",
                    "size": 5731
                }, {
                    "name": "MaxFlowMinCut",
                    "size": 7840
                }, {
                    "name": "ShortestPaths",
                    "size": 5914
                }, {
                    "name": "SpanningTree",
                    "size": 3416
                }]
            }, {
                "name": "optimization",
                    "children": [{
                    "name": "AspectRatioBanker",
                    "size": 7074
                }]
            }]
        }, {
            "name": "animate",
                "children": [{
                "name": "interpolate",
                    "children": [{
                    "name": "ArrayInterpolator",
                    "size": 1983
                }, {
                    "name": "ColorInterpolator",
                    "size": 2047
                }, {
                    "name": "DateInterpolator",
                    "size": 1375
                }, {
                    "name": "Interpolator",
                    "size": 8746
                }, {
                    "name": "MatrixInterpolator",
                    "size": 2202
                }, {
                    "name": "NumberInterpolator",
                    "size": 1382
                }, {
                    "name": "ObjectInterpolator",
                    "size": 1629
                }, {
                    "name": "PointInterpolator",
                    "size": 1675
                }, {
                    "name": "RectangleInterpolator",
                    "size": 2042
                }]
            }, {
                "name": "ISchedulable",
                "size": 1041
            }, {
                "name": "Parallel",
                "size": 5176
            }, {
                "name": "Pause",
                "size": 449
            }, {
                "name": "Scheduler",
                "size": 5593
            }, {
                "name": "Sequence",
                "size": 5534
            }, {
                "name": "Transition",
                "size": 9201
            }, {
                "name": "Transitioner",
                "size": 19975
            }, {
                "name": "TransitionEvent",
                "size": 1116
            }, {
                "name": "Tween",
                "size": 6006
            }]
        }, {
            "name": "data",
                "children": [{
                "name": "converters",
                    "children": [{
                    "name": "Converters",
                    "size": 721
                }, {
                    "name": "DelimitedTextConverter",
                    "size": 4294
                }, {
                    "name": "GraphMLConverter",
                    "size": 9800
                }, {
                    "name": "IDataConverter",
                    "size": 1314
                }, {
                    "name": "JSONConverter",
                    "size": 2220
                }]
            }, {
                "name": "DataField",
                "size": 1759
            }, {
                "name": "DataSchema",
                "size": 2165
            }, {
                "name": "DataSet",
                "size": 586
            }, {
                "name": "DataSource",
                "size": 3331
            }, {
                "name": "DataTable",
                "size": 772
            }, {
                "name": "DataUtil",
                "size": 3322
            }]
        }]
    }
}
    </script>
  </body>
</html>

在getData2()函数抓取csv_data是错误的。你应该替换

csv_data = d3.select("#csvdata"); // won't work

csv_data = d3.csv.parse(d3.select("pre#csvdata").text()); // works

你可以在这里阅读更多关于选择用d3解析CSV数据

d3.nest()生成带有'key'和'values'属性的嵌套数组。但是树默认使用'children'和'name'。为了将其转换为'name'和'children':1. 您需要指定树的子访问器函数tree.children ()2. 修改节点的文本属性,如下所示:

.text(function(d) { return d.key; })