D3 强制有向节点作为文本 - 计算相对箭头指向位置
d3 forced directed nodes as text - calculate relative arrow pointing position
我想使用 d3 中的强制布局算法可视化有向图。节点应显示为其名称,如下所示的矩形。我的问题是计算箭头应指向的矩形之外的位置。
我认为它应该在 tick() 函数中完成。为了避免像角度计算这样的极端努力,我可以使用截距定理。
我不知道如何获取将使用属性设置的边缘的参数,我找不到这方面的示例。
var force = d3.layout.force().nodes(dataset.nodes).links(dataset.edges)...
var edges = svg.selectAll("line").data(dataset.edges).enter().append("line")...
var nodes = svg.selectAll("text").data(dataset.nodes).enter().append("text")...
force.on("tick", function(){
// Why does the following function not work? How to implement this correctly?
edges.attr(function(d){
var x1 = d.source.x
var y1 = d.source.y
var x2 = d.target.x
var y2 = d.target.y
// ... calulate new source and targetcoordinates ... I can do this myself
return {
"x1": newSourceX,
"y1": newSourceY,
"x2": newTargetX,
"y2": newTargetY
}
});
});
如何实现每个边的函数以提取任何源参数和目标参数并保存新位置?
您认为这是性能最佳的解决方案吗?
尝试使用以下方法作为起点。在tick()中调用updateLines(".links")会将线设置为仅到达给定节点的半径,而不是矩形的边缘。
var updateLines = function (selection) {
selection.each( function(d) {
var x1 = d.source.x,
y1 = d.source.y,
x2 = d.target.x,
y2 = d.target.y,
rad = Math.atan((y2-y1)/(x2-x1)),
offsetX1 = d.source.r * -Math.cos(rad),
offsetY1 = d.source.r * Math.sin(rad),
offsetX2 = d.target.r * Math.cos(rad),
offsetY2 = d.target.r * -Math.sin(rad);
d3.select(this)
.attr("x1", function() {
if (x2 - x1 >= 0) {
return x1 - offsetX1;
} else {
return x1 + offsetX1;
}
})
.attr("y1", function() {
if (x2 - x1 >= 0) {
return y1 + offsetY1;
} else {
return y1 - offsetY1;
}
})
.attr("x2", function() {
if (x2 - x1 >= 0) {
return x2 - offsetX2;
} else {
return x2 + offsetX2;
}
})
.attr("y2", function() {
if (x2 - x1 >= 0) {
return y2 + offsetY2;
} else {
return y2 - offsetY2;
}
})
})
}
我知道您试图避免使用角度,但我认为修改上述功能来解决您的需求不会太复杂。当将一个节点的坐标与另一个节点的坐标进行比较时,想象它们之间的"偏移"x和y值形成一个三角形,因此是一个斜边。如果您查看节点的文本框并想象相邻节点的关系线穿过此文本框,则在那里形成的三角形形状与由所讨论的两个节点的偏移值形成的三角形形状相同。
因此,所有三个角度都是相同的,这意味着只要您知道文本框的尺寸,就应该能够轻松找到需要应用于给定节点坐标的两个值。
完成这项工作所需的另一条信息是考虑在两个节点坐标之间创建的角度是大于还是小于在节点中心坐标 (0,0) 和文本框边缘相对于中心的坐标之间创建的角度:
var yourBool = Math.atan(offsetX/offsetY) > Math.atan( textbox.width / 2 / textbox.height / 2 )
// or Math.atan(y/x) and so on...
我不认为实现这一点会导致您的图形明显滞后,但是,要回答您的最后一个问题,我相信有一种性能更好的方法来实现此功能。
Walters 的答案需要一些更改才能正确处理线端平差,因为在确定添加或减去计算的调整时,需要包括源和目标的 x 和 y 坐标。 例如,要计算 X2 调整:
.attr("x2", function() {
if ((y2 >= y1) && (x2 >= x1)) return x2 - offsetX2;
if ((y2 >= y1) && (x2 < x1)) return x2 + offsetX2;
if ((y2 < y1) && (x2 >= x1)) return x2 - offsetX2;
if ((y2 < y1) && (x2 < x1)) return x2 + offsetX2;
}
- 我可以获得相对于被点击元素的确切点击位置吗
- 根据元素和容器大小计算边距
- 从Rally获取一个特定的标记,以便计算另一个字段中的值
- 使用D3.js计算带有字母间距的文本长度
- 使用CSS或JavaScript计算分页符的数量
- 可以't计算自定义谷歌地图的js
- 固定位置菜单时滚动,直到它击中一个相对容器的底部
- 如何计算每个元素's的高度,并将这些值用作函数中的变量
- 抵消在具有pageY计算的相对容器中位于顶部
- 相对路径的计算
- D3 强制有向节点作为文本 - 计算相对箭头指向位置
- 如何使用 jQuery 计算相对定位元素的绝对位置*没有*
- 计算段落相对于其中内容[数据]的高度(字符数)
- 在javascript中计算相对大小的HTML元素的大小时出错
- 位置相对内容计算高度
- 如何计算元素相对于屏幕的位置
- js:如何计算对象在旋转组中的画布相对位置
- Three.js-计算相对旋转
- 使用一些编程语言(JS/ c#)计算RSI(相对强度指数)
- 当主体可以相对定位时,如何计算dom元素的页面位置