【发布时间】:2019-01-06 03:04:08
【问题描述】:
我创建了一个 d3-force 布局。仅允许在边界框内拖动节点。当节点接近边界时,节点保持固定在其位置,根据以下功能:
function boundX(x) {
return Math.max(0, Math.min(width - (nodeWidth+padding), x));
}
function boundY(y){
return Math.max(0, Math.min(height - (nodeHeight+padding), y))
}
节点通过折线连接。每条折线的特点是两个线段。第一段由源节点的 (d.source.x+nodeWidth/2, d.source.y+nodeHeight/2) 坐标定义,该坐标是节点的中点,也是与目标节点的直线的交点。第二段从与目标节点的交点开始,到目标节点的中点(d.target.x+nodeWidth/2)结束。线与目标节点的交点是沿折线放置标记的位置。这是代码的一部分 - 在刻度函数中 - 负责计算交点并绘制线条:
function tick() {
link.attr("points", function(d) {
var interForw = pointOnRect(d.source.x, d.source.y,
d.target.x - nodeWidth / 2, d.target.y - nodeHeight / 2,
d.target.x + nodeWidth / 2, d.target.y + nodeHeight / 2);
if(d.direction==="forward") {
return boundXInter((d.source.x+nodeWidth/2) + " "
+ boundYInter(((d.source.y) + nodeHeight / 2) + ","
+ boundXInter(((interForw.x+nodeWidth/2))) + " "
+ boundYInter((interForw.y) + nodeHeight / 2) + ","
+ boundXInter(d.target.x+nodeWidth/2) + " "
+ boundYInter((d.target.y) + nodeHeight / 2);
}
这些是定义链接边界的函数:
function boundXInter(x) {
return Math.max(nodeWidth/2, Math.min(width - (nodeWidth/2+padding),x));
}
function boundYInter(y){
return Math.max(nodeHeight/2, Math.min(height - (nodeHeight/2+padding), y));
}
当两个节点像第一张图像中一样位于另一个节点下方时。它的行为符合预期。 。
但是,当节点如下图所示放置时,如果用户继续拖动节点,即使他们不允许进一步移动边界,节点也会被阻止,但链接会继续移动,直到width-nodeWidth/2 点,根据boundXInter 函数。
我想要实现的是交点(标记),在这种情况下,线的第一段不会比它的实际位置移动得更远,如第三张图所示。我希望它是固定的,而不是线段延伸到width-nodeWidth/2 位置,如下图所示。可能,重新格式化 boundXInter 函数可以完成这项工作。但是,我尝试了很多组合,但没有。我想提一下,如果用户停止拖动链接返回到想要的状态(如第二个图所示)
有什么想法吗?在这种情况下,我该怎么做才能获得正确的结果?
您可以在此处找到有效的 sn-p:https://jsfiddle.net/yx2grm4s/39/。
【问题讨论】:
-
能否请您创建一个 sn-p(JsBin、Fiddle 或其他)?帮助更容易
-
你绘制的是相对于节点左上角坐标的所有东西吗?以节点 XY 位置为中心绘制框要容易得多,因此线条在节点 XY 处开始和停止,无需计算 w*.5,h*.5 偏移量,可以使用如果您在
g元素上使用转换,则为负x和y属性。 -
@V.Sambor:我刚刚在问题主体中添加了一个sn-p
-
sn-p 对我不起作用。它不允许我拖动任何东西,并且初始绘制看起来很奇怪。
-
现在应该可以工作了! @rioV8
标签: javascript d3.js force-layout