我是 d3 的完全初學者,數周以來一直被一個問題困擾。
基于示例:https : //jsfiddle.net/t4vzg650/6/我開發了一個帶有 d3 的可折疊力布局。我已成功添加鏈接和音頻(目前僅在本地作業)。但默認情況下,我只希望擴展最佳實踐、工具和課程結構節點,并折疊其他節點。然后可以通過雙擊按需打開它們。我在這里遇到了類似的問題,但我還沒有設法實作它。
var data = {
"name": "Best Practices",
"size": 50,
"color": "#C37B89",
"font": 15,
"children": [{
"name": "Course Structure",
"size": 50,
"color": "#BCCC9A",
"font": 15,
"_children": null,
"children": [{
"name": "x",
"size": 30,
"color": "#BCCC9A",
"font": 8,
"_children": null,
"children" : [{
"name": "x",
"size": 30,
"color": "#BCCC9A",
"font": 8,
}, {
"name": "x",
"size": 30,
"color": "#BCCC9A",
"font": 8,
}
]
}, {
"name": "x",
"size": 30,
"color": "#BCCC9A",
"font": 8,
}]
}, {
"name": "Tools",
"size": 50,
"color": "#EAE7C6",
"font": 15,
"_children": null,
"children": [{
"name": "x",
"size": 30,
"color": "#EAE7C6",
"font": 8
}, {
"name": "x",
"size": 30,
"color": "#EAE7C6",
"font": 8
}]
}]
};
var i = 0;
var root = d3.hierarchy(data);
var nodeSvg, linkSvg, nodeEnter, linkEnter;
var width = 960
var height = 600
var centerx = width/2
var centery = height/2
var svg = d3.select("#network")
.attr("width", width)
.attr("height", height)
.append("g");
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) {
return d.id;
}).distance(100))
.force("charge", d3.forceManyBody().strength(-300))
//center network
.force("center", d3.forceCenter(centerx, centery))
.on("tick", ticked);
update();
function update() {
var nodes = flatten(root);
var links = root.links()
linkSvg = svg.selectAll(".link")
.data(links, function(d) {
return d.target.id;
})
linkSvg.exit().remove();
var linkEnter = linkSvg.enter()
.append("line")
.attr("class", "link");
linkSvg = linkEnter.merge(linkSvg)
nodeSvg = svg.selectAll(".node")
.data(nodes, function(d) {
return d.id;
})
nodeSvg.exit().remove();
var nodeEnter = nodeSvg.enter()
.append("g")
.attr("class", "node")
.on("dblclick", click)
.call(d3.drag()
.on("end", dragended))
nodeEnter.append("circle")
.attr("r", function(d) {return d.data.size})
.attr("fill", function(d) {return d.data.color})
nodeEnter.append("text")
.text(function(d) {
return d.data.name;})
.attr("font-size", function(d) {return d.data.font})
.attr("class", "headline")
nodeSvg = nodeEnter.merge(nodeSvg);
simulation
.nodes(nodes)
simulation.force("link")
.links(links);
}
function ticked() {
linkSvg
.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;
});
nodeSvg
.attr("transform", function(d) {
return "translate(" d.x ", " d.y ")";
});
}
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
update();
simulation.restart();
} else {
d.children = d._children;
d._children = null;
update();
simulation.restart();
}
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0)
d.fx = null
d.fy = null
}
function flatten(root) {
var nodes = [];
function recurse(node) {
if (node.children) node.children.forEach(recurse);
if (!node.id) node.id = i;
else i;
nodes.push(node);
}
recurse(root);
return nodes;
}
我的代碼在這里:https : //codepen.io/LaraB1612/pen/bGreEWV
如果有人可以幫助我,我會很高興。
非常感謝
uj5u.com熱心網友回復:
我已經想出了如何實作這一點:
- 不需要在click方法的每個條件下都運行update和restart方法,檢查條件后一次就夠了:
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update();
}
- 呼叫 flatten 方法后需要呼叫 update 方法。在這種情況下,您還需要展平根的兩個子項,工具和課程結構。它可能不是最優雅的解決方案,但它有效:
var flattenedChildOne = flatten(root.children[0]);
var flattenedChildTwo = flatten(root.children[1]);
flattenedChildOne.forEach(function(d) {
d._children = d.children;
d.children = null;
});
flattenedChildTwo.forEach(function(d) {
d._children = d.children;
d.children = null;
});
update();
- 我
"_children": null已從您的資料中洗掉了所有內容,它們是不必要的。
我在這里解決了這個問題:https : //jsfiddle.net/orsisi/tnv37wxr/39/
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/329037.html
標籤:javascript d3.js 力布局
