D3 v4力导向图矩形节点

3
在下面的力导向图中,我希望矩形在保持水平距离不变的同时,能够垂直靠近彼此:

var data = {
   "nodes":[  
      {  
         "name":"Abc",
         "id":"1",
         "value":"1",
         "cvr":"123"
      },
      {  
         "name":"Aaa",
         "id":"2",
         "value":"0.25",
         "cvr":"7445"
      },
      {  
         "name":"JTY",
         "id":"3",
         "value":"0.25",
         "cvr":"24582"
      },
      {  
         "name":"TTT",
         "id":"4",
         "value":"0.1",
         "cvr":"12351"
      },
      {  
         "name":"MMM",
         "id":"5",
         "value":"0.15",
         "cvr":"783456"
      },
      {  
         "name":"KLI",
         "id":"6",
         "value":"0.05"
      },
      {  
         "name":"OTP",
         "id":"7",
         "value":"0.250"
      },
      {  
         "name":"Tasqu",
         "id":"8",
         "value":"0.250"
      },
      {  
         "name":"Mii",
         "id":"9",
         "value":"0.10"
      },
      {  
         "name":"YrA",
         "id":"11",
         "value":"0.150",
         "cvr":"10096669"
      },
      {  
         "name":"Tarb",
         "id":"10",
         "value":"0.1500"
      }
   ],
   "links":[  
      {  
         "source":"2",
         "target":"1"
      },
      {  
         "source":"3",
         "target":"1"
      },
      {  
         "source":"4",
         "target":"1"
      },
      {  
         "source":"5",
         "target":"1"
      },
      {  
         "source":"6",
         "target":"1"
      },
      {  
         "source":"7",
         "target":"2"
      },
      {  
         "source":"8",
         "target":"3"
      },
      {  
         "source":"9",
         "target":"4"
      },
      {  
         "source":"11",
         "target":"5"
      },
      {  
         "source":"10",
         "target":"11"
      }
   ]
};

// Create somewhere to put the force directed graph
var svg = d3.select("svg"),
    width = +svg.attr("width"),
    height = +svg.attr("height");

var rectWidth = 240;
var rectHeight = 60;
var minDistance = Math.sqrt(rectWidth*rectWidth + rectHeight*rectHeight);

// Set up the simulation and add forces
var simulation = d3.forceSimulation()
 .nodes(data.nodes);

var link_force =  d3.forceLink(data.links)
 .id(function(d) { return d.id; }).distance(minDistance).strength(1);

var charge_force = d3.forceManyBody()
    .strength(-1000);

var center_force = d3.forceCenter(width / 2, height / 2);

simulation
    .force("charge_force", charge_force)
    .force("center_force", center_force)
    .force("links",link_force);


// Add tick instructions:
simulation.on("tick", tickActions );

// Add encompassing group for the zoom
var g = svg.append("g")
    .attr("class", "everything");

var div = g.select("body").append("div")
    .attr("class", "tooltip")
    .style("opacity", 0);

// Draw lines for the links
var link = g.append("g")
 .attr("class", "links")
  .selectAll("line")
  .data(data.links)
  .enter()
   .append("line")
    .attr("stroke-width", 2)
    .style("stroke", linkColour);

// Draw rects and texts for the nodes
var nodes = g.append("g")
 .attr("class", "nodes");

var node = nodes.selectAll("node")
 .data(data.nodes)
 .enter()
  .append("g");

node
 .on("mouseover", function(d) {
  d3.select(this).select("rect").style("fill", "red");
  div.transition()
   .duration(200)
   .style("opacity", .9);
  div.html("asdasd")
   .style("left", (d3.event.pageX) + "px")
   .style("top", (d3.event.pageY - 28) + "px");
 })
 .on("mouseout", function(d) {
  d3.select(this).select("rect").style("fill", rectColour);
  div.transition()
   .duration(500)
   .style("opacity", 0);
 });


var rect = node.append("rect")
  .attr("x", -rectWidth/2)
  .attr("y", -rectHeight/2)
  .attr("width", rectWidth)
  .attr("height", rectHeight)
  .attr("fill", rectColour);

var textName = node.append("text")
  .text(function (d) { return d.name; })
  .attr("y", -15)
  .style("text-anchor", "middle");

var textCvr = node.append("text")
  .text(function (d) { return d.cvr; })
  .attr("y", 0)
  .style("text-anchor", "middle");

var textOwned = node.append("text")
  .text(function (d) { return (parseFloat(d.value)*100).toFixed(2)+"%"; })
  .attr("y", 15)
  .style("text-anchor", "middle");

node.attr("transform", function(d) {
    return "translate(" + d.x + "," + d.y + ")"
});

// Add drag capabilities
var drag_handler = d3.drag()
 .on("start", drag_start)
 .on("drag", drag_drag)
 .on("end", drag_end);

drag_handler(node);

// Add zoom capabilities
var zoom_handler = d3.zoom()
    .on("zoom", zoom_actions);

zoom_handler(svg);

/** Functions **/

function rectColour(d){
 if(d.person){
  return "blue";
 } else {
  return "pink";
 }
}

// Function to choose the line colour and thickness
function linkColour(d){
 return "black";
}

// Drag functions
function drag_start(d) {
 if (!d3.event.active) simulation.alphaTarget(0.3).restart();
    d.fx = d.x;
    d.fy = d.y;
}

// Make sure you can't drag the rect outside the box
function drag_drag(d) {
  d.fx = d3.event.x;
  d.fy = d3.event.y;
}

function drag_end(d) {
  if (!d3.event.active) simulation.alphaTarget(0);
  d.fx = null;
  d.fy = null;
}

// Zoom functions
function zoom_actions(){
    g.attr("transform", d3.event.transform)
}

function tickActions() {
    // update node positions each tick of the simulation
 node.attr("transform", function(d) {
  return "translate(" + d.x + "," + d.y + ")"
 });
    // update link positions
 link
  .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 width="600" height="600"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>

如何更改使得x轴上的最小距离基于rectWidth,而y轴上的最小距离基于rectHeight?同时,它们不应该在对角线上重叠。

1个回答

2

至少它朝着正确方向前进,但现在矩形有点水平扩展。它们无法垂直堆叠。而且,当试图将一个矩形放在中心节点上方时,仍然会产生巨大的间隙。我想我想做的事情有点复杂。 - Marcus Persson
好的,我明白了这个想法,但我还没有答案。这就是我不喜欢矩形节点的原因。我会在有时间的时候尝试检查一下。我认为我们必须调整链接距离、链接强度或其他某些东西。我会尝试在文档中找到一些线索。 - Frederic Kuhner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接