我试图创建像this这样的力量有向图。当我使用样本数据时,它画得很好。但是当我使用自己的数据时,节点似乎是从svg大小中提取出来的。 这是我得到的:
这是我的代码:
var nodes = createFDGNodes(stopsByLine);
var links = createFDGLinks(stopsByLine);
var simulation = d3.forceSimulation()
.force("link", d3.forceLink()
.id(function(d) { return d.id; })
)
.force("charge", d3.forceManyBody()
.distanceMin(function(d) {return 1; })
)
.force("center", d3.forceCenter(960/2, 500/2));
const circleGroup = d3.select("div.transit-network")
.append("svg")
.attr("width", 960)
.attr("height", 500)
.append("g")
.attr("class","fdg");
var color = d3.scaleOrdinal(d3.schemeCategory20);
var link = circleGroup.append("g")
.attr("class", "links")
.selectAll("line")
.data(links)
.enter().append("line")
.attr("stroke", "black")
.attr("stroke-width", 1);
var node = circleGroup.append("g")
.attr("class", "nodes")
.selectAll("circle")
.data(nodes)
.enter().append("circle")
.attr("r", 5)
.attr("class", function(d) {return "line-"+d.lineId+" stop-"+d.id;})
.attr("fill", function(d){
return color(d.lineId);
});
simulation.nodes(nodes)
.on("tick", ticked);
simulation.force("link")
.links(links);
function ticked() {
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; });
node
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
}
如何制作图表以便在分配的svg大小中绘制?
答案 0 :(得分:1)
"正确"在您所分配的区域内进行模拟拟合的方法是调整模拟中的所有力,例如forceManyBody
,forceLink
,forceCenter
等......
但是,您可以强制模拟(无双关语)以适应给定区域。例如,在下面的演示中,使用tick
函数内的模拟将模拟约束在100 x 100像素的小区域中:
node.attr("transform", (d) => {
return "translate(" + (d.x < 10 ? dx = 10 : d.x > 90 ? d.x = 90 : d.x) +
"," + (d.y < 10 ? d.y = 10 : d.y > 90 ? d.y = 90 : d.y) + ")"
})
以下是演示:
var width = 100;
var height = 100;
var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
var nodes = [{
"id": "foo"
}, {
"id": "bar"
}, {
"id": "baz"
}, {
"id": "foobar"
}];
var edges = [{
"source": 0,
"target": 1
}, {
"source": 0,
"target": 2
}, {
"source": 0,
"target": 3
}];
var simulation = d3.forceSimulation()
.force("link", d3.forceLink())
.force("charge", d3.forceManyBody().strength(-1000))
.force("center", d3.forceCenter(width / 2, height / 2));
var links = svg.selectAll("foo")
.data(edges)
.enter()
.append("line")
.style("stroke", "#ccc")
.style("stroke-width", 1);
var color = d3.scaleOrdinal(d3.schemeCategory20);
var node = svg.selectAll("foo")
.data(nodes)
.enter()
.append("g");
var nodeCircle = node.append("circle")
.attr("r", 5)
.attr("stroke", "gray")
.attr("stroke-width", "2px")
.attr("fill", "white");
simulation.nodes(nodes);
simulation.force("link")
.links(edges);
simulation.on("tick", function() {
node.attr("transform", (d) => {
return "translate(" + (d.x < 10 ? dx = 10 : d.x > 90 ? d.x = 90 : d.x) + "," + (d.y < 10 ? d.y = 10 : d.y > 90 ? d.y = 90 : d.y) + ")"
})
links.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;
})
});
&#13;
svg{
background-color: lemonchiffon;
}
&#13;
<script src="https://d3js.org/d3.v4.min.js"></script>
&#13;
答案 1 :(得分:0)
只需使用.strength函数调整; e.g。
.force("charge", d3.forceManyBody().strength(-5) )
答案 2 :(得分:0)
Mike Bostock的Bounded force layout也有效,您可以设置半径以匹配您的节点。
node.attr("cx", function(d) { return d.x = Math.max(radius, Math.min(width - radius, d.x)); })
.attr("cy", function(d) { return d.y = Math.max(radius, Math.min(height - radius, d.y)); });