如何解决如何在 d3 圆包装中拖动带有孩子的节点?
我一直在尝试使用此代码作为基础 https://codepen.io/MrHen/pen/GZQOPW 拖入 d3 打包节点。不幸的是,我找不到一种方法可以使用,这样当带有子节点的节点被拖动时,它的(可见)子节点会随着父节点移动。我用这个函数来拖动圆圈:
var drag = d3.behavior.drag()
.on("drag",function(d,i) {
d.x += d3.event.dx;
d.y += d3.event.dy;
draw();
})
例如,在上面的示例中,我希望能够拖动第 1 层(浅蓝色)上的节点,当我这样做时,他们的孩子会改变他们的位置,以便他们(在视觉上)留在父母的边界内。
>谢谢!
解决方法
首先删除根节点和中间节点上的pointer-events: none
。然后设置一个小递归来遍历一个节点的后代并更新它们的位置:
function recurOnChildren(d) {
d.x += d3.event.dx;
d.y += d3.event.dy;
if (!d.children) return;
d.children.forEach(c => {
recurOnChildren(c);
});
}
并从您的拖动处理程序调用:
var drag = d3.behavior.drag()
.on("drag",function(d,i) {
recurOnChildren(d);
draw();
})
运行代码:
var margin = 20,diameter = 960;
var color = d3.scale.linear()
.domain([-1,5])
.range(["hsl(152,80%,80%)","hsl(228,30%,40%)"])
.interpolate(d3.interpolateHcl);
var pack = d3.layout.pack()
.padding(2)
.size([diameter - margin,diameter - margin])
.value(function(d) {
return d.size;
})
var svg = d3.select("body").append("svg")
.attr("width",diameter)
.attr("height",diameter)
.append("g")
.attr("transform","translate(" + diameter / 2 + "," + diameter / 2 + ")");
d3.json("https://gist.githubusercontent.com/mbostock/7607535/raw/695f8ed6298c06a946406c707200a1f6b21875d8/flare.json",function(error,root) {
if (error) throw error;
var focus = root,nodes = pack.nodes(root),view;
function recurOnChildren(d) {
d.x += d3.event.dx;
d.y += d3.event.dy;
if (!d.children) return;
d.children.forEach(c => {
recurOnChildren(c);
});
}
var drag = d3.behavior.drag()
.on("drag",i) {
recurOnChildren(d);
draw();
})
var circle = svg.selectAll("circle")
.data(nodes)
.enter().append("circle")
.attr("class",function(d) {
return d.parent ? d.children ? "node node--middle" : "node node--leaf" : "node node--root";
})
.style("fill",function(d) {
return d.children ? color(d.depth) : null;
});
var text = svg.selectAll("text")
.data(nodes)
.enter().append("text")
.attr("class","label")
.style("fill-opacity",function(d) {
return d.parent === root ? 1 : 0;
})
.style("display",function(d) {
return d.parent === root ? "inline" : "none";
})
.text(function(d) {
return d.name;
});
var node = svg.selectAll("circle,text");
svg.selectAll(".node").call(drag);
d3.select("body")
.style("background",color(-1))
draw();
function draw() {
var k = diameter / (root.r * 2 + margin);
node.attr("transform",function(d) {
return "translate(" + (d.x - root.x) * k + "," + (d.y - root.y) * k + ")";
});
circle.attr("r",function(d) {
return d.r * k;
});
}
});
.node {
cursor: pointer;
}
.node:hover {
stroke: #000;
stroke-width: 1.5px;
}
.node--leaf {
fill: white;
}
.label {
font: 11px "Helvetica Neue",Helvetica,Arial,sans-serif;
text-anchor: middle;
text-shadow: 0 1px 0 #fff,1px 0 0 #fff,-1px 0 0 #fff,0 -1px 0 #fff;
}
.label {
pointer-events: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。