【发布时间】:2013-08-06 01:39:31
【问题描述】:
我目前正在我的力布局中实现箭头,如本示例 (http://bl.ocks.org/mbostock/1153292) 中所做的那样,并且效果很好。然而,人们很快就会意识到箭头的位置和大小在这里是硬编码的,因为节点永远不会改变大小。
如果我动态更改节点大小,我有一个图表,因此我希望箭头相应更新,否则它们会被节点覆盖或覆盖节点,或者只是不连接到节点。
我发现只有一篇帖子 (linking nodes of variable radius with arrows) 谈到了这个问题。然而,它没有得到回答,并且一张海报给出的答案是让边缘在节点的半径而不是中心结束,这不是我想做的事情。这需要不断地重新计算边缘位置,考虑到我拥有的边缘数量是不切实际的。
我认为这会相对简单,但无法弄清楚。我目前正在进行的更改是将标记创建移动到节点的生成之下,否则除非我想运行我正在使用的大小方法,否则无法获取节点大小数据,这将大量浪费处理能力(我有数百个节点)。
我正在尝试什么(粗略的例子,我的代码有点复杂)
var path = svg.append("svg:g").selectAll("path")
.data(force.links())
.enter().append("svg:path")
.attr("class", function(d) { return d.target.nodeID; });
var circle = svg.append("svg:g").selectAll("circle")
.data(force.nodes())
.enter().append("svg:circle")
.attr("r", nodeSize) //Dynamically determine size
.call(force.drag);
// Per-node markers, as each node could potentially have a unique size
svg.append("svg:defs").selectAll("marker")
.data(nodes, function(d) { return d.nodeID; })
.enter().append("svg:marker")
.attr("id", function(d) { return d.nodeID; })
.attr("viewBox", "0 -5 10 10")
.attr("refX", function(d) { return d.r; }) //Offset by the radius of the node
.attr("refY", 0)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.append("svg:path")
.attr("d", "M0,-5L10,0L0,5");
//Now that we know radius data for nodes, add the arrows in
path.each(function(d) {
d.attr("marker-end", function(d) { return "url(#" + d.target.nodeID + ")"; })
});
有人知道解决此问题的最佳方法吗?提前致谢!
更新:根据请求,我创建了一个 jsfiddle (http://jsfiddle.net/herbstmb/j5wJ7/)。这是我试图让动态箭头大小起作用的基本力布局。
【问题讨论】:
-
你能把这段代码 sn-p 变成一个有效的fiddle吗?看起来没有多少遗漏,并且可以让其他人更容易尝试找出解决方案。
-
我创建了一个。检查帖子中的更新。这是一个非常基本的力布局,我只是想向其中添加动态大小的箭头。
-
控制台抱怨的语法错误在上一行,您用单引号打开一个字符串并用双引号关闭它。关于您的问题,我注意到您提出了几个关于丢弃潜在解决方案的问题,因为在数百个节点上运行的潜在性能问题。您可能应该尝试最简单的解决方案并在丢弃它之前对其进行测试。你会惊讶于你可以在一瞬间对几百个点做多少。如今的浏览器速度很快(相对而言,即使是移动设备)。
-
感谢您的发现。我很欣赏尝试最简单的解决方案,而且我实际上相信我正在尝试的解决方案(即使我不知道该怎么做)就是那个解决方案。老实说,可视化对我来说已经有点慢了,所以我一直在努力寻找提高速度的方法。我希望添加这个新功能不会产生什么影响。不过我会试一试的!
标签: javascript svg d3.js force-layout