有an example我们可以点击一个圆圈并查看内部圆圈。
兵力布局也有不同的例子。
是否可以有一个力布局,并且它的每个节点将/可以是具有内力布局的圆?
因此,它将作为这些圆圈的无限缩放(带有额外的数据加载)。
欢迎任何想法/示例。
最佳答案
我会这样解决这个问题:构建一个强制导向的布局,从其中一个教程开始(可能是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 元素可能会更清晰。
现在缩小。首先,您需要为反向过程设置一个不同的缩放阈值,控件中的滞后效应将有助于防止有人使用鼠标滚轮时出现跳跃的可视化效果。你放大它就会膨胀,然后你必须再缩小一点,然后它才会再次收缩。
好的,当您达到缩小阈值时,您只需删除子元素并将父元素添加回子元素位置的质心即可。
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 提到的,这可能需要一些时间。
关于javascript - 无限缩放强制布局d3.js,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26468152/