14

I'm trying to make a force directed graph using d3.layout.force, and I need the container to be resizable - that is I'd like to be able calculate appropriate charge and linkDistance values based on the size, or have d3 do it for me in some magical way.

I've made an attempt (link: http://jsfiddle.net/VHdUe/6/) which only uses nodes. I'm setting the charge to a value that's based on the number of nodes that would fit across the radius of the circle that it tends to be shaped like.

The solution works for some middle-sized containers, but if you click resize a few times, you can see it doesn't really work for all sizes...

The only way forward I can see is using an svg scale transform, which will mess up the size of my elements unfavorable. Any other options?

PS: I have seen http://mbostock.github.com/d3/talk/20110921/bounding.html (the answer to D3 force directed layout with bounding box), but I'd rather have a gravity-based solution than a bounding box one.

4

1 回答 1

21

除了chargelinkDistance,你还有gravity。如果您希望图表保持与布局大小相同的相对密度,那么您需要同时缩放电荷和重力。这些是决定 blob 整体大小的两个主要计算力。有关更多详细信息,请参阅我的力布局演讲

我尝试了几个不同的版本,这个版本似乎工作得很好:

var k = Math.sqrt(nodes.length / (width * height));

layout
    .charge(-10 / k)
    .gravity(100 * k)

这里nodes.length / (width * height)与图密度成线性比例:节点面积除以布局面积。电荷力遵循平方反比定律,所以这可以解释为什么平方根运作良好。D3 的“重力”是一个虚拟弹簧,它随着与布局中心的距离线性缩放,因此随着图形变得更密集,这也会增加重力,并阻止节点逃离边界框。

于 2012-03-29T16:35:09.920 回答