18

MikeBostockの階層エッジバンドル図の修正バージョンを作成しています。

http://mbostock.github.com/d3/talk/20111116/bundle.html

しかし、次のように、特定のデータグループにまたがるアークを作成したいと思います。

ここに画像の説明を入力してください

現在、円弧の長さをハードコーディングしていますが、動的にコーディングしたいと思います。どうすればこれを達成できますか?これが私の現在のコードです:

/* MH - USER DEFINED VARIABLES */
var chartConfig = { "Tension" : .85, "canvasSize" : 800, "dataFile" : "../data/projects.json", "linePadding" : 160, "textPadding" : 30, "arcPadding" : 5, "arcWidth" : 30 }
var pi = Math.PI;

var radius = chartConfig.canvasSize / 2,
    splines = [];

var cluster = d3.layout.cluster() //Cluster is the diagram style, a node to link dendrogram dendrogram (tree diagram)
    .size([360, radius - chartConfig.linePadding]); //MH - sets the size of the circle in relation to the size of the canvas

var bundle = d3.layout.bundle(); //Bundles the node link lines so that they spread at the end but keep close initially

var arcInner = radius - chartConfig.linePadding + chartConfig.arcPadding;
var arcOuter = arcInner + chartConfig.arcWidth;
var arc = d3.svg.arc().innerRadius(arcInner).outerRadius(arcOuter);

var line = d3.svg.line.radial()
    .interpolate("bundle")
    .tension(chartConfig.Tension) //How tightly to bundle the lines. No tension creates straight lines
    .radius(function(d) { return d.y; })
    .angle(function(d) { return d.x / 180 * Math.PI; });

var vis = d3.select("#chart").append("svg")
    .attr("width", radius * 2)
    .attr("height", radius * 2)
    .attr("class","svg")
    .append("g")
    .attr("class","chart")
    .attr("transform", "translate(" + radius + "," + radius + ")");


d3.json(chartConfig.dataFile, function(classes) {
  var nodes = cluster.nodes(packages.root(classes)),
      links = packages.imports(nodes),
      splines = bundle(links);

  var path = vis.selectAll ("path.link")
      .data(links)
      .enter().append("path")
      .attr("class", function(d){ return "link source-" + d.source.key + " target-" + d.target.key; })
      .attr("d", function(d,i){ return line(splines[i]); });

  vis.selectAll("g.node")
      .data(nodes.filter(function(n) { return !n.children; }))
    .enter().append("g")
      .attr("class", "node")
      .attr("id",function(d){ return "node-" + d.key; })
      .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; })
    .append("text")
      .attr("dx", function(d) { return d.x < 180 ? chartConfig.textPadding : -chartConfig.textPadding; }) //dx Moves The text out away from the lines in a positive or negative direction, depending on which side of the axis it is on
      .attr("dy", ".31em") //moves the text up or down radially around the circle
      .attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
      .attr("transform", function(d) { return d.x < 180 ? null : "rotate(180)"; })
      .text(function(d) {
        textString = d.key;
        textString = textString.split('_').join(' '); //MH replace underscores with spaces
        return textString; 
      })
      .on("mouseover",textOver)
      .on("mouseout",textOut);

});


/* ARCS ARE HARDCODED, SHOULD BE DYNAMIC */

var arcData = [
  {aS: 0, aE: 45,rI:radius - chartConfig.linePadding + chartConfig.arcPadding,rO:radius - chartConfig.linePadding + chartConfig.textPadding-chartConfig.arcPadding}
];

var arcJobsData = d3.svg.arc().innerRadius(arcData[0].rI).outerRadius(arcData[0].rO).startAngle(degToRad(1)).endAngle(degToRad(15));
var g = d3.select(".chart").append("svg:g").attr("class","arcs");
var arcJobs = d3.select(".arcs").append("svg:path").attr("d",arcJobsData).attr("id","arcJobs").attr("class","arc");
g.append("svg:text").attr("x",3).attr("dy",15).append("svg:textPath").attr("xlink:href","#arcJobs").text("JOBS").attr("class","arcText"); //x shifts x pixels from the starting point of the arc. dy shifts the text y units from the top of the arc

... 

function degToRad(degrees){
  return degrees * (pi/180);
}

function updateNodes(name,value){
  return function(d){
    if (value) this.parentNode.appendChild(this);
    vis.select("#node-"+d[name].key).classed(name,value);
  }
}
4

1 に答える 1

17

ここであなたのjsonデータ構造を見てきました:http://mikeheavers.com/transfers/projects/data/projects.json。まず、データをグループ化してタグを正しく追加するには、次のようにデータを変更することをお勧めします: https ://raw.github.com/gist/4172625/4de3e6a68f9721d10e0068d33d1ebb9780db4ae2/flare-imports.json hirarchical構造。

次に、グループを使用して円弧を描画できます。

まず、「selectAll」でグループを作成し、ノードをフィルタリングします。ここで、データの他のグループ名を追加できます。

var groupData = svg.selectAll("g.group")
  .data(nodes.filter(function(d) {return (d.key=='Jobs' || d.key == 'Freelance' || d.key == 'Bayard') && d.children; }))
.enter().append("group")
  .attr("class", "group");

私の場合はそれを確認したので、フィルターの結果を確認し、ケースに応じて変更することをお勧めします(データ構造は少し異なります)。

これで、グループのリストが表示されました。次に、各グループの子を調べ、開始角度と終了角度として最小と最大のxを選択します。次のような関数を作成できます。

function findStartAngle(children) {
    var min = children[0].x;
    children.forEach(function(d){
       if (d.x < min)
           min = d.x;
});
return degToRad(min);
}

同様に、minをmaxに置き換えることによるfindEndAngle関数。次に、アークのフォーマットを作成できます。

var groupArc = d3.svg.arc()
  .innerRadius(arcData[0].rI)
  .outerRadius(arcData[0].rO)
  .startAngle(function(d){return findStartAngle(d.children);})
  .endAngle(function(d){return findEndAngle(d.children);});

次に、「動的」な方法でアークを作成できます。

svg.selectAll("g.arc")
  .data(groupData[0])
.enter().append("arc")
  .attr("d", groupArc)
  .attr("class", "arc")
    .append("svg:text")
      ...;

私の場合はgroupData[0]ですが、自分の場合はチェックする必要があります。アークにタグを追加するには、選択の結果に応じてd.keyまたはd.nameを追加する必要があります。

アークの例

完全なコードはここから入手できます:https ://gist.github.com/4172625 。データベースからjsonを取得するたびに、一般的なアークへの動的な方法がない場合、私は死んでしまいます:Pお役に立てば幸いです。

于 2012-11-29T11:19:58.433 に答える