2014-10-20 79 views
1

an example我们可以点击一个圆圈并看到内圈。
也有不同的力布局的例子。无限放大力布局d3.js

是否可以有一个力布局,它的每个节点将会/可以是一个具有内力布局的圆?
因此,它将作为这些圆圈的无限缩放(带有额外的数据加载)。

欢迎任何想法/例子。

+2

是的,这是可能的。您需要将力量和包装布局结合起来。 [本教程](http://www.delimited.io/blog/2013/12/19/force-bubble-charts-in-d3)不是那样,但可能有所帮助。 – 2014-10-20 14:43:02

+0

谢谢,@LarsKotthoff,但也许有这些的一些例子?在每个例子中,所有数据一次加载。我需要动态加载它在一个特定的缩放级别... – Andron 2014-10-20 16:35:45

+0

我不知道任何具体做你要找的例子。 – 2014-10-20 17:12:29

回答

1

我会这样处理这个问题:从一个教程开始(也许this one,因为它构建了一些使用圆圈打包进行初始化的东西),构建一个强制定向布局。添加D3的缩放行为。

var force = d3.layout.force() 
// force layout settings 

var zoom = d3.behavior.zoom() 
// etc. 

到目前为止,这么好。除了强制布局喜欢在[width/2, height/2]附近闲逛外,如果你围绕着[0, 0]居中,它会使缩放变得更容易。与geometric zooming战斗一段时间,直到你意识到这个问题真的需要semantic zooming。实现语义缩放。去喝杯咖啡。

找出您的圈子大小和缩放级别之间的关系,可以让您知道何时需要揭示下一个级别。类似这样的:

// expand when this percent of the screen is covered 
var coverageThreshold = 0.6; 
// the circles should be scaled to this size 
var maxRadius = 20; 
// the size of the visualization 
var width = 960; 
// which means this is the magic scale factor 
var scaleThreshold = maxRadius/(coverageThreshold * width) 
// note: the above is probably wrong 

现在,实现一个空间数据过滤器。当你放大时,你基本上想要隐藏任何已缩小视图的数据点,这样你就不会浪费GPU时间来计算它们的表示。另外,找出一个算法来确定用户正在放大哪个节点。这很好,可能会使用Voronoi tessalation。学习方式比你想象的更需要几何。

我们需要解决的另一个数学问题。我们将让子节点代替父节点,所以我们需要根据父节点的总大小来缩放它们的大小。这会很烦人,需要调整才能正确使用,除非你知道正确的算法......我不知道。

// size of the parent node 
var parentRadius = someNumberPossiblyCalculated; 
// area of the parent node 
var parentArea = 2 * Math.PI * parentRadius; 
// percent of the the parent's area that will be covered by children 
// (here be dragons) 
var childrenCoverageRatio = 0.8; 
// total area covered by children 
var childrenArea = parentArea * childrenCoverageArea; 
// the total of the radiuses of the children 
var childTotal = parent.children 
    .map(radiusFn) 
    .reduce(function(a, b) { return a + b; }); 

// the child radius function 
// use this to generate the child elements with d3 
// (optimize that divide in production!) 
var childRadius = function(d) { 
    return maxRadius * radiusFn(d)/childTotal; 
}; 
// note: the above is probably wrong 

好的,现在我们已经准备好了制作魔法酱的作品了。在zoom处理程序中,针对您的参考点检查d3.event.scale。如果用户已经放大过去吧,请执行以下步骤非常迅速:

  • 隐藏父元素是关闭屏幕
  • 删除被放大到
  • 父节点添加子节点在父的X和Y位置是父布局的
  • 明确运行force.tick()的时间屈指可数让孩子移开一点
  • 可能使用循环包装设计,使这个过程更清洁

好的,所以现在我们有一个很好的小缩放布局。放大时,您会达到一定的阈值,希望通过可视化代码自动计算。当你这样做时,你放大的节点“爆炸”到所有它的组成节点中。

现在弄清楚如何构建代码,以便您可以“重置”事情,让您继续放大并再次发生。这可能是递归的,但将尺度缩小几个数量级并同时将SVG元素扩大反比因子可能会更清晰。

Now zooming out。首先,你需要一个明显的缩放阈值来控制逆向过程,这是控制器中的滞后效应,如果有人骑着鼠标滚轮,这将有助于防止可视化。你放大并扩大,然后你必须再缩小一点,然后再缩小。

好吧,当您点击缩小阈值时,您只需放下子元素并将父元素添加回到子元素位置的质心。

var parent.x = d3.mean(parent.children, function(d) { return d.x; }); 
var parent.y = d3.mean(parent.children, function(d) { return d.y; }); 

而且,你缩小开始展示你而放大躲在那些节点。

正如@Lars提到的,这可能会需要一点时间。