d3.js可折叠的力布局,所有节点都已折叠



我一直在尝试使用我编写的json文件来实现定向力布局。在我尝试让它从所有节点崩溃开始之前,它工作正常。我为所有节点声明了一个名为"index"的属性,指示它们属于树的哪个级别(根的索引是0,它的子级是1,等等)我猜节点的"索引"属性有问题,因为当我第一次启动页面时,它们的值是正确的,但当我折叠并重新打开一个节点时,相关节点的索引值会发生变化,并且不再正确绘制链接。

为什么每当我点击任何东西时,它都会不断更改从json中获取的索引值,或者你有什么参考项目可以帮助我解决这个问题吗?

谢谢,

这是我的脚本代码:

var indx = 0;
var width = 1260, height = 1220, root;
var force = d3.layout.force().linkDistance(80).charge(-300)
.gravity(.05).size([ width, height ]).on("tick", tick);
var svg = d3.select("#chart").append("svg")
.attr("width", width).attr("height", height);
var link = svg.selectAll(".link"), node = svg
.selectAll(".node");
var text = svg.selectAll(".link");

d3.json("graph.json", function(error, json) {
root = json;
update();
});
function toggle(d) {
indx = d.index;
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update();
}
function prepareLinks(allNodes) {
var newLinks = new Array();
var allLinks = d3.layout.tree().links(allNodes);
for ( var i = 0; allLinks.length > i; i++) {
if (allLinks[i].source.index <= indx) {
console.log("source : " + allLinks[i].source.index
+ "-" + allLinks[i].source.name);
newLinks.push(allLinks[i]);
}
console.log(allLinks[i].target.index + "-"
+ allLinks[i].target.name);
}
for ( var i = 0; newLinks.length > i; i++) {
console.log("newLinks : " + newLinks[i].source.index
+ "-" + newLinks[i].source.name);
console.log(newLinks[i].target.index + "-"
+ newLinks[i].target.name);
}
return newLinks;
}
function update() {
var nodes = flatten(root, indx);
var links = prepareLinks(nodes);

// Restart the force layout.
force.nodes(nodes).links(links).start();
// Update links.   
link = link.data(links, function(d) {
return d.target.id;
});
link.exit().remove();
link.enter().insert("line", ".node").attr("class", "link");
svg.selectAll("g.ltext").remove();
text = svg.append("svg:g").selectAll("g").data(links);
text.enter().append("svg:g").attr("class", "ltext");
text.append("svg:text").attr("class", "linktext").attr(
"dx", 5).attr("dy", ".35em").text(
function(d) {
return d.source.type;
});
// Update nodes.
node = node.data(nodes, function(d) {
return d.id;
});
node.exit().remove();
var nodeEnter = node.enter().append("g").attr("class",
"node").on("click", function(d) {
toggle(d);
update(d);
}).call(force.drag);
nodeEnter.append("circle").attr("r", function(d) {
return Math.sqrt(d.size) / 10 || 10;
});
nodeEnter.append("text").attr("dy", ".35em").text(
function(d) {
return d.name;
});
node.select("circle").style("fill", color);
}
function tick() {
link.attr("x1", function(d) {
return d.target.x;
}).attr("y1", function(d) {
return d.target.y;
}).attr("x2", function(d) {
return d.source.x;
}).attr("y2", function(d) {
return d.source.y;
});
node.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
text.attr("transform", function(d) {
var sourcex = d.source.x;
var sourcey = d.source.y;
var targetx = d.target.x;
var targety = d.target.y;
return "translate(" + (sourcex + targetx) / 2 + ","
+ (sourcey + targety) / 2 + ")";
});
}
function color(d) {
return d._children ? "#BA8343" // collapsed package
: d.children ? "#7C4C6B" // expanded package
: "#6F704A"; // leaf node
}
// Toggle children on click.
function click(d) {
if (d3.event.defaultPrevented)
return; // ignore drag
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update(d);
}
// Returns a list of all nodes under the root.
function flatten(root, indx) {
var nodes = [], i = 0;
function recurse(node) {
console.log("flatten'da başta index: " + node.index
+ "ad " + node.name);
if (node.children) {
node.children.forEach(recurse);
}
if (!node.id)
node.id = ++i;
if (indx >= node.index || indx + 1 == node.index) {
nodes.push(node);
//                          console.log("flatten'da index: "+ node.index+ "ad "+ node.name);
}
}
recurse(root);
return nodes;
}

下面是我的json文件中的一个例子:

{
"name": "Data Mining","type":"related","index":2,
"children": [
{
"name": "Yapay Sinir Ağları", "size": 7074,"type":"related","index":3,
"children": [
{
"name": "Compututional Intelligence","type":"narrower","index":4,
"children":[
{"name": "Genetik Algoritmalar", "size": 7074,"type":"related","index":5},
{"name": "Bulanık Mantık", "size": 7074,"type":"related","index":5},
{"name":"Soft Computing","type":"related","index":5,
"children": [
{"name": "Esnek Hesaplama", "size": 7074,"type":"related","index":6}
]
} 
]
}
]
}

问题很可能是index是d3部队布局中节点的保留属性,当节点属性更新时,它会被覆盖。

force.nodes([nodes])

如果指定了节点,则将布局的关联节点设置为指定的数组。如果未指定节点,则返回当前数组,默认为空数组。每个节点都有以下内容属性:

index-节点数组中节点的从零开始的索引。

x-当前节点位置的x坐标。

y-当前节点位置的y坐标。

px-上一个节点位置的x坐标。

py-上一个节点位置的y坐标。

fixed-指示节点位置是否锁定的布尔值。

weight—节点权重;关联链接的数量。

在将节点传递给布局如果未设置它们,则适当的默认值将由初始化调用start时的布局但是,请注意,如果您在节点上存储其他数据时,数据属性不应该与布局使用的上述属性冲突

文档

为了防止冲突,请将json中的index属性重命名为其他属性。在我自己的项目中,我指的是给定节点与根的距离,因为它是depth

最新更新