javascript - 创建 sunburst 以接受 csv 数据

标签 javascript d3.js

我可能在学会走路之前尝试过运行,但我使用了以下两个引用:

http://codepen.io/anon/pen/fcBEe

https://bl.ocks.org/mbostock/4063423

从一开始,我就尝试使用函数 buildHierarchy(csv) 将 csv 文件输入到 sunburst 中。其余代码来自 Mike Bostock 的示例。

我已将数据范围缩小到非常简单的范围,如下所示:

var text = 
    "N-CB,50\n\
     N-TrP-F,800\n";

所以我认为这会产生三个同心环 - 确实如此 - 但我希望内环能够按照数据中的 800:50 比例进行分割。为什么我会得到我现在得到的戒指?

<!DOCTYPE html>
<meta charset="utf-8">
<style>
  #sunBurst {
    position: absolute;
    top: 60px;
    left: 20px;
    width: 250px;
    height: 300px;
  }
  
  body {
    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
    margin: auto;
    position: relative;
    width: 250px;
  }
  
  form {
    position: absolute;
    right: 20px;
    top: 30px;
  }
</style>
<form>
  <label>
    <input type="radio" name="mode" value="size" checked> Size</label>
  <label>
    <input type="radio" name="mode" value="count"> Count</label>
</form>
<script src="//d3js.org/d3.v3.min.js"></script>
<div id="sunBurst"></div>
<script>

  var text = 
    "N-CB,50\n\
     N-TrP-F,800\n";


  var csv = d3.csv.parseRows(text);
  var json = buildHierarchy(csv);


  var width = 300,
    height = 250,
    radius = Math.min(width, height) / 2,
    color = d3.scale.category20c();

  //this bit is easy to understand:
  var svg = d3.select("#sunBurst").append("svg")

  .attr("width", width)
    .attr("height", height)
    .append("g")
    .attr({
      'transform': "translate(" + width / 2 + "," + height * .52 + ")",
      id: "sunGroup"
    });

  // it seems d3.layout.partition() can be either squares or arcs
  var partition = d3.layout.partition()
    .sort(null)
    .size([2 * Math.PI, radius * radius])
    .value(function(d) {
      return 1;
    });

  var arc = d3.svg.arc()
    .startAngle(function(d) {
      return d.x;
    })
    .endAngle(function(d) {
      return d.x + d.dx;
    })
    .innerRadius(function(d) {
      return Math.sqrt(d.y);
    })
    .outerRadius(function(d) {
      return Math.sqrt(d.y + d.dy);
    });



  var path = svg.data([json]).selectAll("path")
    .data(partition.nodes)
    .enter()
    .append("path")
    .attr("display", function(d) {
      return d.depth ? null : "none";
    })
    .attr("d", arc)
    .style("stroke", "#fff")
    .style("fill", function(d) {
      return color((d.children ? d : d.parent).name);
    })
    .attr("fill-rule", "evenodd")
    .style("opacity", 1)
    .each(stash);



  d3.selectAll("input").on("change", function change() {
    var value = this.value === "size" ? function() {
      return 1;
    } : function(d) {
      return d.size;
    };

    path
      .data(partition.value(value).nodes)
      .transition()
      .duration(2500)
      .attrTween("d", arcTween);
  });
  //});

  // Stash the old values for transition.
  function stash(d) {
    d.x0 = d.x;
    d.dx0 = d.dx;
  }

  // Interpolate the arcs in data space.
  function arcTween(a) {
    var i = d3.interpolate({
      x: a.x0,
      dx: a.dx0
    }, a);
    return function(t) {
      var b = i(t);
      a.x0 = b.x;
      a.dx0 = b.dx;
      return arc(b);
    };
  }

  d3.select(self.frameElement).style("height", height + "px");


  // Take a 2-column CSV and transform it into a hierarchical structure suitable
  // for a partition layout. The first column is a sequence of step names, from
  // root to leaf, separated by hyphens. The second column is a count of how 
  // often that sequence occurred.
  function buildHierarchy(csv) {
    var root = {
      "name": "root",
      "children": []
    };
    for (var i = 0; i < csv.length; i++) {
      var sequence = csv[i][0];
      var size = +csv[i][1];
      if (isNaN(size)) { // e.g. if this is a header row
        continue;
      }
      var parts = sequence.split("-");
      var currentNode = root;
      for (var j = 0; j < parts.length; j++) {
        var children = currentNode["children"];
        var nodeName = parts[j];
        var childNode;
        if (j + 1 < parts.length) {
          // Not yet at the end of the sequence; move down the tree.
          var foundChild = false;
          for (var k = 0; k < children.length; k++) {
            if (children[k]["name"] == nodeName) {
              childNode = children[k];
              foundChild = true;
              break;
            }
          }
          // If we don't already have a child node for this branch, create it.
          if (!foundChild) {
            childNode = {
              "name": nodeName,
              "children": []
            };
            children.push(childNode);
          }
          currentNode = childNode;
        } else {
          // Reached the end of the sequence; create a leaf node.
          childNode = {
            "name": nodeName,
            "size": size
          };
          children.push(childNode);
        }
      }
    }
    return root;
  };
</script>

plunker 上还有一个进一步的实例:https://plnkr.co/edit/vqUqDtPCRiSDUIwfCbnY?p=preview

最佳答案

您的 buildHierarchy 函数会考虑空格。所以,当你写

  var text = 
    "N-CB,50\n\
     N-TrP-F,800\n";

它实际上是两个根节点:

'N' and '     N'

您有两个选择:

  1. 使用非空白文本,如

     var text = 
        "N-CB,50\n" +
        "N-TrP-F,800\n";
    
  2. 修复 buildHierarchy 函数以 trim 空格。

关于javascript - 创建 sunburst 以接受 csv 数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40247642/

相关文章:

javascript - 向用户呈现多条确认消息的最佳方式

javascript - 如何使用 gulp-sass 插件提高 Gulp 任务性能?

javascript - 如何使用 css3 为文本中的字母设置动画?

javascript - d3 条形图上的 y 刻度

database - 将数据保存/存储/写入数据库的 native d3.js 方法?

javascript - 使用 jquery 动态添加文件输入?

javascript - 如何获取值作为类型并将其添加到一个文本区域中?

javascript - 交叉过滤器和D3 : Filter by group AND dimension

javascript - 为什么这个 TopoJSON 用 D3 渲染得这么小? (简单的例子)

javascript - 使用 d3.js 创建词云