Javascript D3Js使用调用更新错误的元素
我是D3JS新手,你可以在 我正面临一个问题,任何指点都会有帮助 当我移动直线时,它会像预期的那样分开,但当我尝试将圆移开时,它会跳回直线 在检查阵列时,当我移动链接时,圆形阵列似乎正在更新,不确定是什么原因导致了这种情况 在此方面的任何帮助都将不胜感激。下面是我在JSFIDLE上的代码Javascript D3Js使用调用更新错误的元素,javascript,d3.js,Javascript,D3.js,我是D3JS新手,你可以在 我正面临一个问题,任何指点都会有帮助 当我移动直线时,它会像预期的那样分开,但当我尝试将圆移开时,它会跳回直线 在检查阵列时,当我移动链接时,圆形阵列似乎正在更新,不确定是什么原因导致了这种情况 在此方面的任何帮助都将不胜感激。下面是我在JSFIDLE上的代码 var width = 960, height = 500; graph1 = {"nodes":[{"x":444,"y":275},{"x":378,"y":324}],"links":[{"sou
var width = 960,
height = 500;
graph1 = {"nodes":[{"x":444,"y":275},{"x":378,"y":324}],"links":[{"source":1,"target":0}]}
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
var onDraggable = function(d1) {
console.log(d1);
d1.x = d3.event.x, d1.y = d3.event.y;
d3.select(this).attr("cx", d1.x).attr("cy", d1.y);
//console.log(d1);
link.filter(function(l) { return l.source === d1; }).attr("x1", d3.event.x).attr("y1", d3.event.y);
link.filter(function(l) { return l.target === d1; }).attr("x2", d3.event.x).attr("y2", d3.event.y);
}
var drag = d3.behavior.drag()
.origin(function(d) { return d; })
.on("drag", onDraggable)
var onDraggable1 = function(d) {
//d.x1 = d3.event.x1, d.y1 = d3.event.y1, d.x2=d3.event.x2, y2=d3.event.y2;
var mouseX = d3.mouse(this)[0];
var mouseY = d3.mouse(this)[1];
var relativeX = mouseX-d.source.x;
var relativeY = mouseY-d.source.y;
console.log(d);
//console.log(d);
// d3.select(this).attr("x1", d3.event.x).attr("y1", d3.event.y).attr("x2", d3.event.x).attr("y2", d3.event.y);
d.source.x= d.source.x+relativeX;
d.source.y = d.source.y+relativeY;
d.target.x= d.target.x+relativeX;
d.target.y = d.target.y+relativeY;
d3.select(this).attr("x1", d.source.x).attr("y1", d.source.y);
d3.select(this).attr("x2", d.target.x).attr("y2", d.target.y);
}
var drag1 = d3.behavior.drag()
.origin(function(d) { return d; })
.on("drag", onDraggable1);
graph1.links.forEach(function(d) {
d.source = graph1.nodes[d.source];
d.target = graph1.nodes[d.target];
});
var node = svg.append("g").attr("class","node")
.selectAll("circle")
.data(graph1.nodes)
.enter().append("circle")
.attr("r", 4)
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.call(drag);
var link = svg.append("g").attr("class","link")
.selectAll("line")
.data(graph1.links)
.enter().append("line")
.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; })
.attr("stroke-width", 2)
.attr("stroke", "black")
.call(drag1);
即使在移动线之后,节点也会“跳跃”到线的末端,这是因为节点的数据对象与线的源/目标数据对象是相同的。节点的
d
值和链接的d.source
或d.target
值只是指向浏览器内存中相同对象的指针(引用)。对该数据对象所做的一切都会反映在链接和节点中。这就是节点拖动功能的作用:直接更改数据对象,然后更新直线和圆的位置以匹配其已更改的数据值
因此,即使在移动直线时不更新圆的cx
和cy
位置,直线拖动方法中的语句d.source.x=
等正在为节点设置d.x
和d.y
值。然后,在节点拖动方法中,当您访问这些值以确定新位置时,移动是相对于线的端点而不是屏幕上圆的位置确定的
那么,如何获得想要的行为,将线与节点分离?开始拖动线时,需要为线的源和目标创建一个新的数据对象,该对象不再引用节点的数据对象。只需在拖动开始时执行一次,因此可以使用拖动行为对象的:
var drag1 = d3.behavior.drag()
.origin(function(d) { return d; })
.on("dragstart", separateNodes);
.on("drag", onDraggable1);
separateNodes
方法将非常简短。我们所要做的就是,对于链接的目标和源,创建一个新的数据对象,它是现有目标/源对象的副本(但可以独立于原始对象进行编辑)。Javascript没有任何用于复制对象的默认方法(尽管如此),但是如果所讨论的对象只是由x和y属性组成,那么很容易做到
var separateNodes = function(d) {
//create new data objects that are copies of d.source and d.target
var newSource = {x:d.source.x, y:d.source.y};
var newTarget = {x:d.target.x, y:d.target.y};
//set the new objects as the target/source of this link
d.source = newSource;
d.target = newTarget;
}
您甚至可以跳过变量声明,只需将它们合并成一行作为源代码,一行作为目标代码,但我发现这样更容易理解。然而,我应该提到,这种方法是有效的,因为x和y都只是简单的数据类型(数字),而不是指向对象的指针。因此,当它说x:d.source.x
时,实际上您得到了该编号的新副本,您可以更改该副本,而不会影响包含该编号的原始对象
但是,如果您的节点和链接也有一个值
属性,该属性是一个复杂的数据对象,那么您必须决定当该行从节点分离时要执行的操作:是要创建整个值数据对象的副本,还是要维护到原始对象的链接,还是用null(空/未定义)替换它对象第一种情况比较复杂,取决于值对象的数据结构;第二,你不需要做任何事情(除了记住你有多个指向同一个对象的指针);对于最后一种情况,只需在separateNodes
函数中的newSource
和newTarget
对象定义中添加值:null、
属性
希望一切都有意义,--ABR你能澄清你想要的行为是什么吗?您希望直线和圆一起移动,还是希望它们完全独立?单击圆并拖动时,直线将展开,但同时单击直线并拖动时,直线应移动。这两种方法都有效。问题是,线与圆分离后,如果尝试将圆移开,它将返回并连接到线。因此,当移动线时,它应该与节点分离(并保持分离,以便不再连接到该节点)?另一种可能是您希望将线和节点一起移动,而不是像移动节点时那样拉伸/扭曲。正确的想法是将节点和线分开,并能够独立移动节点。感谢您的澄清;请看下面的答案。谢谢,这就完成了我想要的。我是D3JS的新手,接下来的问题是,你们怎么知道他们在浏览器中引用的是同一个对象?有没有什么工具和调试方法可以用来解决这些问题呢?还有一个问题,如果我想将节点连接回测线,那么当我拖动节点时,测线会展开……类似于我们开始时的情况。实现这一点的最佳方法是什么?或者换句话说,我如何在特定条件下将它们重新关联到同一个对象?我是如何发现的?我查看了其他拖动方法的代码,以了解它们是如何工作的。但这是一个标准特性(如果很容易忘记的话)——所有引用对象和数组的变量都只是指针。这是将指针连接在一起的行吗?d.source=graph1.nodes[d.source];d、 target=graph1.nodes[d.target];