2017-08-20 95 views
3

在d3.js强制布局中,给出重力值会使布局循环。如何让d3.js强制布局重力矩形?

enter image description here 不过,我想使力布局的矩形,而节点有一个负电荷和甚至距离。 (如上所述)

有什么办法可以让力布局成矩形吗?

我可以通过修改滴答功能来实现吗?

这里是我的代码:

var background = d3.select('.background'); 
 

 
var width = background.node().getBoundingClientRect().width, 
 
\t height = background.node().getBoundingClientRect().height; 
 

 
var nodes = d3.range(50).map(function(d, i) { 
 
\t \t return { 
 
     \t \t text: "Hello" 
 
\t \t }; 
 
\t }); 
 

 
var messages = background.selectAll('.message') 
 
\t .data(nodes) 
 
\t .enter() 
 
\t \t .append('div') 
 
\t \t .attr('class', 'message') 
 
\t \t .text(d => d.text) 
 
\t \t .each(function(d, i) { 
 
\t \t \t d.width = this.getBoundingClientRect().width; 
 
\t \t \t d.height = this.getBoundingClientRect().height; 
 
\t \t }); 
 

 
var force = d3.layout.force() 
 
\t .gravity(1/88) 
 
\t .charge(-50) 
 
\t .nodes(nodes) 
 
\t .size([width, height]); 
 

 
messages.call(force.drag); 
 

 
force.on('tick', function(e) { 
 
\t messages.each(d => { 
 
\t \t d.x = Math.max(0, Math.min(width - d.width, d.x)); 
 
\t \t d.y = Math.max(0, Math.min(height - d.height, d.y)); 
 
\t }); 
 
\t 
 
\t messages.style('left', d => `${d.x}px`) 
 
\t \t .style('top', d => `${d.y}px`); 
 
}); 
 

 
force.start();
body { 
 
    padding: 0; 
 
    margin: 0; 
 
} 
 
.background { 
 
    width: 100%; 
 
    height: 100vh; 
 
    border: 1px solid #007aff; 
 
} 
 
.message { 
 
    display: inline-block; 
 
    font-family: sans-serif; 
 
    border-radius: 100vh; 
 
    color: white; 
 
    padding: 10px; 
 
    background-color: #007aff; 
 
    position: absolute; 
 
} 
 
.boundary { 
 
    display: inline-block; 
 
    width: 10px; 
 
    height: 10px; 
 
    background-color: red; 
 
    position: absolute; 
 
}
<script src="https://d3js.org/d3.v3.min.js"></script> 
 
<body> 
 
    <div class="background"> 
 
    </div> 
 
</body>

+0

是的,有。是的,它涉及修改滴答功能。然而,这里没有人会写代码来展示如何去做(我的意思是我不会),在这种情况下没有代码的答案是没有意义的。因此,发布**您的代码**创建的力量,与滴答功能,所以我们只需要修改它。 –

+0

@GerardoFurtado哦,我明白了。我赞同你。我用我的代码更新了我的帖子!谢谢。 – Stleamist

回答

2

OK,编辑3:d3v4,forceCollide可用于设置节点之间的最小距离,如果你再使用一个积极的力量,这将节点绘制在一起,帮助将它们设置为相等的距离(尽管它看起来比圆形的圆更好):

var force = d3.forceSimulation(nodes) 
.force("charge", d3.forceManyBody().strength(-10)) 
.force("collide", d3.forceCollide(30).strength(1).iterations(1)) 
.force('x', d3.forceX(width/2).strength(0.5)) 
.force('y', d3.forceY(height/2).strength(10)); 

假设节点是矩形SVG,SVG的中心内,限制他们可以帮助甚至出了边线:

position.nodes(nodes).on('tick', function ticks() { 
     nodes.attr("cx", function(d) { 
      return d.x = Math.max(20, Math.min(width + 20, d.x)) 
     }).attr("cy", function(d) { 
      return d.y = Math.max(20, Math.min(height + 20, d.y)); 
     }) 
    }); 

,并与力优势玩耍可以帮助吸引他们沿y轴:

var position = d3.forceSimulation(nodes).force("charge", d3.forceManyBody()) 
.force('x', d3.forceX(width/2).strength(1)) 
.force('y', d3.forceY(height/2).strength(5)); 

fiddle here.

看来,军队是V4比V3多了很多定制的,我觉得forceCollide集成了一些变通到库中。因此,您可以尝试找到v3解决方法,或者考虑升级到v4。

在v3中,我使用重力,充电和限制x和y来保持盒子中的节点更好一点,fiddle here.但是我对v3的了解不够多,不能完全改善它。

+0

谢谢!我应该检查d3.js v4。 'forceX/Y'方法对我来说非常有用。 – Stleamist