javascript - How to make d3.js force layout gravity rectangular? -


in d3.js force layout, giving gravity value makes layout circular.

enter image description here however, i'd make force layout rectangular, while nodes have negative charge , even distance. (like above)

is there way make force layout rectangular?

can achieve modifying tick function?

here code:

var background = d3.select('.background');    var width = background.node().getboundingclientrect().width,  	height = background.node().getboundingclientrect().height;    var nodes = d3.range(50).map(function(d, i) {  		return {        		text: "hello"  		};  	});    var messages = background.selectall('.message')  	.data(nodes)  	.enter()  		.append('div')  		.attr('class', 'message')  		.text(d => d.text)  		.each(function(d, i) {  			d.width = this.getboundingclientrect().width;  			d.height = this.getboundingclientrect().height;  		});    var force = d3.layout.force()  	.gravity(1/88)  	.charge(-50)  	.nodes(nodes)  	.size([width, height]);    messages.call(force.drag);    force.on('tick', function(e) {  	messages.each(d => {  		d.x = math.max(0, math.min(width - d.width, d.x));  		d.y = math.max(0, math.min(height - d.height, d.y));  	});  	  	messages.style('left', d => `${d.x}px`)  		.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>

ok, edit 3: in d3v4, forcecollide can used set minimum distances between nodes, if use positive strength, draws nodes together, helping set them distance apart (although looks better circles rectangles):

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)); 

assuming nodes in rectangular svg, limiting them within centre of svg can out edges:

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));         })     }); 

and playing around force strengths can draw them in along y-axis:

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.

it seems forces lot more customisable in v4 v3, think forcecollide integrated workarounds library. so, can try , find v3 workaround, or maybe upgrading v4.

in v3 played around gravity, charge , limiting x , y maintain nodes in box bit better, fiddle here. don't know enough v3 improve beyond that.


Comments

Popular posts from this blog

ubuntu - PHP script to find files of certain extensions in a directory, returns populated array when run in browser, but empty array when run from terminal -

php - How can i create a user dashboard -

javascript - How to detect toggling of the fullscreen-toolbar in jQuery Mobile? -