我是D3的新手,我正在尝试创建一个交互式网络可视化。我复制了this示例的大部分内容,但我通过使用SVG“线”而不是“路径”将曲线改为直线,并根据节点表示的数据对节点进行缩放。问题是我的箭头(用SVG标记创建)在线条的末尾。由于一些节点很大,箭头隐藏在它们后面。我希望我的箭头显示在它们所指向的节点的外边缘。
下面是我创建标记和链接的方法:
svg.append("svg:defs").selectAll("marker")
.data(["prereq", "coreq"])
.enter().append("svg:marker")
.attr("id", String)
.attr("viewBox", "0 -5 10 10")
.attr("refX", 15)
.attr("markerWidth", 6)
.attr("markerHeight", 6)
.attr("orient", "auto")
.append("svg:path")
.attr("d", "M0,-5L10,0L0,5");
var link = svg.selectAll(".link")
.data(force.links())
.enter().append("line")
.attr("class", "link")
.attr("marker-end", function(d) { return "url(#" + d.type + ")"; });
我注意到"refX“属性指定箭头应该显示在离行尾多远的地方。我怎么才能让它依赖于它所指向的节点的半径呢?如果我不能这样做,我可以改为改变线条本身的端点吗?我猜我会在这个函数中做到这一点,它会随着所有东西的移动而重置线条的端点:
function tick() {
link
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
circle.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
text.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
}
哪种方法更有意义,我该如何实现它?
发布于 2013-05-26 05:29:19
谢谢Lars Kotthoff,我按照另一个问题的建议完成了这项工作!首先,我从使用行切换到了路径。我不认为我真的必须这样做,但这使我更容易遵循我正在查看的其他示例,因为它们使用了路径。
然后,我向我的节点添加了一个"radius“字段。我只是在设置radius属性时执行此操作,将其添加为实际字段,而不是立即返回值:
var circle = svg.append("svg:g").selectAll("circle")
.data(force.nodes())
.enter().append("svg:circle")
.attr("r", function(d) {
if (d.logic != null) {
d.radius = 5;
} else {
d.radius = node_scale(d.classSize);
}
return d.radius;
然后,我编辑了tick()函数,将这个半径考虑在内。这需要一些简单的几何学知识。
function tick(e) {
path.attr("d", function(d) {
// Total difference in x and y from source to target
diffX = d.target.x - d.source.x;
diffY = d.target.y - d.source.y;
// Length of path from center of source node to center of target node
pathLength = Math.sqrt((diffX * diffX) + (diffY * diffY));
// x and y distances from center to outside edge of target node
offsetX = (diffX * d.target.radius) / pathLength;
offsetY = (diffY * d.target.radius) / pathLength;
return "M" + d.source.x + "," + d.source.y + "L" + (d.target.x - offsetX) + "," + (d.target.y - offsetY);
});
基本上,路径形成的三角形,它的总x变化(diffX)和它的总y变化(diffY)是一个类似于由目标节点内部的路径段(即节点半径)、目标节点内部的x变化(offsetX)和目标节点内部的y变化(offsetY)形成的三角形。这意味着目标节点半径与总路径长度的比率等于offsetX与diffX的比率以及offsetY与diffY的比率。
我还将箭头的refX
值更改为10。我不确定为什么这是必要的,但现在它似乎起作用了!
发布于 2014-01-04 19:22:38
我回答了同样的问题over here。答案使用向量数学,它对其他计算也很有用。
https://stackoverflow.com/questions/16660193
复制相似问题