D3.js如何将力布局的节点排列在圆上

时间:2014-03-16 16:54:26

标签: javascript d3.js force-layout

我开发了一种力量布局来表示社交群体之间的关系。现在我想让节点分布在一个带有连接它们的链接的圆圈中。做这个的最好方式是什么?

代码的完整版本(没有数据)在这里http://jsfiddle.net/PatriciaW/zZSJT/ (为什么我也必须在这里包含代码?这是主要部分)

d3.json("/relationships?nocache=" + (new Date()).getTime(),function(error,members){
   var links=members.organizations.map(function(members) {
      return members.member;
      });

var nodes = {};

links.forEach(function(link) {
  link.source = nodes[link.xsource] || (nodes[link.xsource] = {source: link.xsource, name: link.xsource, category: link.categorysource, path: link.pathsource, desc: link.descsource, title: link.titlesource});
  link.target = nodes[link.xtarget] || (nodes[link.xtarget] = {target: link.xtarget, name: link.xtarget, category: link.categorytarget, path: link.pathtarget, desc: link.desctarget, title: link.titletarget});
});

force = d3.layout.force()
.nodes(d3.values(nodes))
.links(links)
.size([width, height])
.charge(-120)
.linkDistance(function() {return (Math.random() * 200) + 100;})
.linkStrength(0.5)
.on("tick", tick)
.start();

var link = svg.selectAll(".link")
.data(force.links())
.enter().append("line")
.attr("class", "link");

var node_drag = d3.behavior.drag()
    .on("dragstart", dragstart)
    .on("drag", dragmove)
    .on("dragend", dragend);

var loading = svg.append("text")
.attr("x", width / 2)
.attr("y", height / 2)
.attr("dy", ".35em")
.style("text-anchor", "middle")
.text("Simulating. One moment please…");

function dragstart(d, i) {
    force.stop() // stops the force auto positioning before you start dragging
}

function dragmove(d, i) {
    d.px += d3.event.dx;
    d.py += d3.event.dy;
    d.x += d3.event.dx;
    d.y += d3.event.dy; 
    tick(); // this is the key to make it work together with updating both px,py,x,y on d !
}

function dragend(d, i) {
    d.fixed = true; // of course set the node to fixed so the force doesn't include the node in its auto positioning stuff
    tick();
    force.resume();
};

var node = svg.selectAll(".node")
.data(force.nodes())
.enter().append("g")
.attr("class", "node")
.on("mouseover", mouseover)
.on("mouseout", mouseout)
.on("click", clickAlert)
.call(node_drag);

node.append("circle")
.attr("r", 8)
.style("fill", function(d) { 
   return categoryColour [d.category];
   })  

// add an image marker
node.append("image")
  .attr("x",-8)
  .attr("y",-8)
  .attr("width", 16)
  .attr("height", 16)
  .attr("xlink:href", function(d) {
      return categoryImage [d.category]
   })
  .on("click", clickAlert)
  .style("cursor", "pointer")

node.append("text")
  .attr("x", 12)
  .attr("dy", ".35em")
  .text(function(d) { 
      return d.name; 
      });
// Use a timeout to allow the rest of the page to load first.
setTimeout(function() {

// Run the layout a fixed number of times.
// The ideal number of times scales with graph complexity.
force.start();
for (var i = n * n; i > 0; --i) force.tick();
force.stop();

svg.selectAll("line")
.data(links)
.enter().append("line")
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });

svg.selectAll("circle")
.data(nodes)
.enter().append("circle")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", 4.5);

loading.remove();
}, 10);

function tick() {
link
  .attr("x1", function(d) { 
       return d.source.x + xadj; })
  .attr("y1", function(d) { 
       return d.source.y + yadj; })
  .attr("x2", function(d) { 
       return d.target.x +xadj; })
  .attr("y2", function(d) { 
       return d.target.y +yadj; });
node
  .attr("transform", function(d) { 
       return "translate(" + (d.x + xadj) + "," + (d.y + yadj) + ")"; 
  });
};

function mouseover() {
 d3.select(this).select("circle").transition()
  .duration(750)
  .attr("r", 16);
d3.select(this).select("text")
   .attr("font-size","34px")
   .style("font-weight", "bold");
};

function mouseout() {
d3.select(this).select("circle").transition()
 .duration(750)
 .attr("r", 8);
d3.select(this).select("text")
  .attr("font-size","12px")
  .style("font-weight", "normal");
};
}) // end json

1 个答案:

答案 0 :(得分:2)

此处someone else's solution

  

此网络图使用D3力布局绘制节点和链接,但不是使用d3.force()来查找最佳节点位置,而是绘制一个不可见的弧并沿圆周均匀放置节点。

<div>
  <p>
    some text on here 1
  </p>
  <i>
    some italic 
  </i>
  <b>text</b>
  <i>
    here
  </i>
  <p>
    text text text
  </p>
  <b>
    some bold text on here
  </b>
</div>