D3 v4拖放树节点到新的父级子级中 [英] D3 v4 drag/drop tree node into new parents children

查看:187
本文介绍了D3 v4拖放树节点到新的父级子级中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用D3中的4个时,我在调整下面的代码片段以完全更新节点及其所有子节点时遇到了一些麻烦.

I'm having a bit of trouble tweaking the snippet below to fully update a node and all of its children when using 4 of D3.

将一个节点拖放到另一个父节点(在"dragend"事件上)时将触发此代码.目的是将拖动的节点从其当前父节点中删除,并将其插入新的父子节点中.

This code fires when a node is dragged and dropped into another parent node (on "dragend" event). It's purpose is to remove the dragged node from its current parent node and insert it into a new parents children.

当前的代码实际上仍然按照使用v4时的意图进行操作,但是现在在新版本中似乎还需要更新到"draggingNode",因此它将可以正确过渡到新位置.至少需要将"draggingNode"应用为新的父",并将其深度"更新为树中新位置. "draggingNode"的每个子级也需要将其深度"更新为树中的新位置.

The current code actually still does what it's intended to do when using v4 but now with the new version there seems to be a few more things that need to be updated to the "draggingNode" so it will transition properly into its new position. At minimum, the "draggingNode" needs to be applied it's new "parent" and also update it's "depth" to where it's new position is within the tree. Each child of the "draggingNode" also needs to have its "depth" updated to it's new position within the tree.

  • selectedNode :"draggingNode"所在的节点(新父节点)
  • draggingNode :当前正在拖动的节点
  • selectedNode: node the "draggingNode" is dropped on (new parent)
  • draggingNode: node currently being dragged

目标代码段(完整的源代码):

var index = draggingNode.parent.children.indexOf(draggingNode);
if (index > -1) {
    draggingNode.parent.children.splice(index, 1);
    // had to update the "draggingNode" parent "children" array if it's 
    // empty otherwise the "firstWalk()" core function throws an error when
    // trying to call "children[0]".
    if (draggingNode.parent.children.length == 0) {
        draggingNode.parent.children = null;
    }
}
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);
}

我相信上面的代码可以保持不变,但是我需要做的是为"draggingNode"添加一些更新,以便可以对其进行正确的更新.

I believe the code above can remain untouched, but what I need to do is add in some updates for the "draggingNode" so that it can be updated properly.

我最初的想法是在将其添加到"selectedNode"数组之前,将以下内容简单地添加到上面的片段中:

My initial thoughts were to simply add the following to the snippet above just before adding it into the "selectedNode" array:

draggingNode.parent = selectedNode;
draggingNode.depth = selectedNode.depth + 1;

这很好用!问题在于它仅适用于没有子节点的节点.子节点属性需要更新.

This works great! The issue is that it only works on nodes without children. Child node properties need to be updated.

问题是

如何更新"draggingNode"及其所有子级,以便将其属性适当地调整为新的父级和深度?

How can I update the "draggingNode", and all of its children, so that their properties are properly adjusted to their new parents and depths?

有没有可以使用的功能,例如层次结构分层以正确更新它们?如果是这样,我不太确定如何使这些工作.或者,也许API中没有可用的函数,我只需要遍历所有子项并更新其深度?

Is there a function that I can use like hierarchy or stratify to properly update them? If so I'm not quite sure how to make those work. Or maybe there is no functions available within the API and I just have to loop through all the children and update their depths?

推荐答案

事实证明,我想出了一个对我来说似乎很好的解决方案.拖动的节点并更新其节点深度.

Well turns out I've came up with a solution that seems to work well for me.. I ended up creating a function to traverse through all the descendants of the dragged node and update their node depths.

function setNodeDepth(d) {
    d.depth = d == root ? 0 : d.parent.depth + 1;
    if (d.children) {
        d.children.forEach(setNodeDepth);
    } else if (d._children) {
        d._children.forEach(setNodeDepth);
    }
}

这就是我最终得到的结果.

Here's what I ended up with..

var index = draggingNode.parent.children.indexOf(draggingNode);
if (index > -1) {
    draggingNode.parent.children.splice(index, 1);
    // had to update the "draggingNode" parent "children" array if it's 
    // empty otherwise the "firstWalk()" core function throws an error when
    // trying to call "children[0]".
    if (draggingNode.parent.children.length == 0) {
        draggingNode.parent.children = null;
    }
}

// update the "draggingNode" parent as well as update all its children 
// so that their properties are properly adjusted to their new depths.
draggingNode.parent = selectedNode;
draggingNode.descendants().forEach(setNodeDepth);

// check for visible children.
if (selectedNode.children) {
    selectedNode.children.push(draggingNode);
// check for hidden children.
} else if (selectedNode._children) {
    selectedNode._children.push(draggingNode);
// no children exist, create new children array and add "draggingNode".
} else {
    selectedNode.children = [];
    selectedNode.children.push(draggingNode);
}

这篇关于D3 v4拖放树节点到新的父级子级中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆