带有矩形的D3 v4力导向图

时间:2017-06-22 11:51:00

标签: javascript d3.js force-layout

在下面的力导向图中,我希望矩形在垂直方向上彼此靠近,同时保持水平相同的距离:



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>
&#13;
&#13;
&#13;

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

1 个答案:

答案 0 :(得分:1)

您应该像这样更改模拟:

simulation
  .force("charge_force", charge_force)
  .force("center_force", center_force)
  .force("links",link_force)
  .force('y', d3.forceY(height / 2).strength(0.10));

基本上它会增加Yaxis的重力,但不会增加Xaxis的重力。

有关以下内容的更多信息:https://github.com/d3/d3-force/blob/master/README.md#forceY

更新了小提琴:https://jsfiddle.net/oesgnzho/3/