首先,对不起我的英语不好。
我想做的是:处理所有节点(根节点除外)的拖放操作,如果它们链接到另一个父节点,则更新其父节点。
我的代码中发生了问题:我可以第一次拖动节点并将其拖放到任何地方。但是,当我第二次单击以再次拖动时,它转换为它的原始位置。当我尝试将一个节点链接到其他父节点时,svg路径被绘制在一个奇怪的位置。
我适应d3v5的Code(老实说,我不会因为面临这个问题而使用d3v3,除非没有解决方案)。 Similar question是我在SO中找到的,但该解决方案无法正常工作。 Tutorial拖放我尝试在代码中复制的d3v5,但没有成功。
我的代码:https://jsfiddle.net/mewlee/0w5jzhnf/48/
function initiateDrag(d, domNode) {
draggingNode = d;
d3.select(domNode).select('.ghostCircle').attr('pointer-events', 'none');
d3.selectAll('.ghostCircle').attr('class', 'ghostCircle show');
d3.select(domNode).attr('class', 'node activeDrag');
svgGroup.selectAll("g.node").sort(function(a, b) { // select the parent and sort the path's
if (a.id != draggingNode.id) return 1; // a is not the hovered element, send "a" to the back
else return -1; // a is the hovered element, bring "a" to the front
});
// if nodes has children, remove the links and nodes
if (nodesDragDrop.length > 1) {
// remove link paths
links = nodesDragDrop.slice(1);
nodePaths = svgGroup.selectAll("path.link")
.data(links, function(d) {
return d.id;
}).remove();
// remove child nodes
nodesExit = svgGroup.selectAll("g.node")
.data(nodesDragDrop, function(d) {
return d.id;
}).filter(function(d, i) {
if (d.id == draggingNode.id) {
return false;
}
return true;
}).remove();
}
// remove parent link
var parent = d3.hierarchy(draggingNode.parent);
parentLink = parent.descendants().slice(1);
svgGroup.selectAll('path.link').filter(function(d,i){
if(d.id==draggingNode.id){
return true;
}
return false;
}).remove();
dragStarted = false;
}
var dragListener = d3.drag()
.on("start", function(d) {
if (d == raiz) {
return;
}
dragStarted = true;
nodesDragDrop = d.descendants();
d3.event.sourceEvent.stopPropagation();
// it's important that we suppress the mouseover event on the node being dragged. Otherwise it will absorb the mouseover event and the underlying node will not detect it
var atual = d3.select(this);
deltaX = atual.attr("x")-d3.event.x;
deltaY = atual.attr("y")-d3.event.y;
})
.on("drag", function(d) {
var node = d3.select(this);
node.attr('x',d.x = d3.event.dx+deltaX);
node.attr('y',d.y = d3.event.dy+deltaY);
if (d == raiz) {
return;
}
if (dragStarted) {
domNode = this;
initiateDrag(d, domNode);
}
d.x0 += d3.event.dy;
d.y0 += d3.event.dx;
node.attr("transform", "translate(" + d.y0 + "," + d.x0 + ")");
updateTempConnector();
}).on("end", function(d) {
if (d == raiz) {
return;
}
domNode = this;
if (selectedNode) {
// now remove the element from the parent, and insert it into the new elements children
var index = draggingNode.parent.children.indexOf(draggingNode);
if (index > -1) {
draggingNode.parent.children.splice(index, 1);
}
if (typeof selectedNode.children !== 'undefined' || typeof selectedNode._children !== 'undefined') {
if (typeof selectedNode.children !== 'undefined') {
selectedNode.children.push(draggingNode);
} else {
selectedNode._children.push(draggingNode);
}
} else {
selectedNode.children = [];
selectedNode.children.push(draggingNode);
}
// Make sure that the node being added to is expanded so user can see added node is correctly moved
expand(selectedNode);
endDrag();
} else {
endDrag();
}
});
function endDrag() {
selectedNode = null;
d3.selectAll('.ghostCircle').attr('class', 'ghostCircle');
d3.select(domNode).attr('class', 'node');
// now restore the mouseover event or we won't be able to drag a 2nd time
d3.select(domNode).select('.ghostCircle').attr('pointer-events', '');
updateTempConnector();
if (draggingNode !== null) {
construir(raiz);
draggingNode = null;
}
}
PS .:可能由于d3.nest在根d3.hierarchy中使用问题,因为“无用”的根节点;并且请不要生我的气,我知道代码很大:(
预先感谢