我试图在d3中绘制我认为相当于力图的东西,但只是在一条扁平线上。我想要大约4-5个不同大小的点,取决于它们的大小,它们之间的均匀间隔(不是中心,但是圆的两边之间的距离应该是恒定的),以及连接它们的线。所以在ASCII格式中,例如:
o---O---o---O
我试图避免一个复杂的计算来计算每条线的中心坐标和开始和结束,所以看起来力布局可能会起作用。不幸的是,当我把它放在一起时,我似乎无法让它工作得很好。通常,时间点最终落后于其他点,因此对于像上面这样的4节点图,它看起来更像是:
O---O
有没有办法让力布局在1维而不是2维?或者我自己坚持做所有的间距计算?我正在使用的代码如下:
var width = 500;
var height = 200;
var svg = d3.select($el[0])
.append('svg')
.attr('width', width)
.attr('height', height);
var data_nodes = [
{ x: width / 2, y: height / 2, count: 5 },
{ x: width / 2, y: height / 2, count: 0 },
{ x: width / 2, y: height / 2, count: 1 },
{ x: width / 2, y: height / 2, count: 10 },
];
var data_links = [
{ source: 0, target: 1 },
{ source: 1, target: 2 },
{ source: 2, target: 3 },
];
var force = d3.layout.force()
.nodes(data_nodes)
.links(data_links)
.linkDistance(150)
.linkStrength(0.5)
.gravity(0.7)
.friction(0.3)
.size([width, height])
.charge(-300);
var links = svg.selectAll('line')
.data(data_links)
.enter()
.append('line')
.attr('stroke', '#65759E')
.attr('stroke-width', 4)
.attr('x1', function (d) { return data_nodes[d.source].x; })
.attr('y1', function (d) { return data_nodes[d.source].y; })
.attr('x2', function (d) { return data_nodes[d.target].x; })
.attr('y2', function (d) { return data_nodes[d.target].y; });
var nodes = svg.selectAll('circle')
.data(data_nodes)
.enter()
.append('circle')
.attr('fill', '#65759E')
.attr('r', function (d) { return 10 + Math.sqrt(d.count) * 4; })
.attr('cx', function (d, i) { return d.x + i * 10; })
.attr('cy', function (d, i) { return d.y; });
force.on('tick', function () {
nodes.attr('cx', function (d) { return d.x; });
links.attr('x1', function (d) { return d.source.x; })
.attr('x2', function (d) { return d.target.x; });
});
force.start();
答案 0 :(得分:0)
你遇到的困难源于这样一个事实,即节点无法绕过彼此,而不会离开正在强行进入的1D线。排斥力阻止节点通过另一个节点的顶部到达另一侧,因此它们被困在这些次优布置中。
默认情况下,d3 force layout会在随机位置初始化节点。但是,您可以在开始布局之前通过设置数据节点对象的x
和y
属性来自行初始化它们。如果使用连续排序的节点初始化图形,根据它们的连接顺序,则力布局可以为您处理间距。