简体   繁体   English

如何使d3.js强制布局重力矩形?

[英]How to make d3.js force layout gravity rectangular?

In d3.js force layout, giving a gravity value makes layout circular. 在d3.js强制布局中,给出重力值使布局呈圆形。

在此输入图像描述 However, I'd like to make force layout rectangular, while nodes have a negative charge and even distance . 但是,我想使力布局成矩形,而节点具有负电荷甚至距离 (like above) (如上)

Is there any way to make force layout rectangular? 有没有办法让力矩布局?

Can I achieve this by modifying tick function? 我可以通过修改tick函数来实现吗?

Here is my 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 => { dx = Math.max(0, Math.min(width - d.width, dx)); dy = Math.max(0, Math.min(height - d.height, dy)); }); messages.style('left', d => `${dx}px`) .style('top', d => `${dy}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 be used to set minimum distances between the nodes, if you then use a positive strength, this draws the nodes together, helping set them an even distance apart (although it looks better for circles than rectangles): 好了,编辑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));

Assuming the nodes are in a rectangular svg, limiting them to within the centre of the SVG can help even out the edges: 假设节点位于矩形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));
        })
    });

and playing around with the force strengths can help draw them in along the y-axis: 并且利用力量力量可以帮助沿着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. 在这里小提琴

It seems that the forces are a lot more customisable in v4 than v3, I think forceCollide integrated some workarounds into the library. 似乎v4中的力量比v3更加可定制,我认为forceCollide将一些变通方法集成到库中。 So, you can try and find a v3 workaround, or maybe look into upgrading to v4. 因此,您可以尝试找到v3解决方法,或者考虑升级到v4。

In v3 I played around with the gravity, charge and limiting x and y to maintain the nodes in the box a bit better, fiddle here. 在第3节中,我玩重力,充电和限制x和y以保持盒子中的节点更好, 在这里摆弄。 But I don't know enough about v3 to improve it much beyond that. 但是我对v3的了解还不够多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM