2017-08-20 93 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