gpt4 book ai didi

javascript - 接受 D3 布局树中的通用嵌套对象

转载 作者:行者123 更新时间:2023-12-02 15:34:03 27 4
gpt4 key购买 nike

我正在创建一棵类似于 D3 Layout Tree 的树并尝试绑定(bind)我的自定义 JSON 对象。切换树节点的代码如下。

function toggleAll(d) {
if (d.children) {
d.children.forEach(toggleAll);
toggle(d);
}
}

// Initialize the display to show a few nodes.
root.children.forEach(toggleAll);
toggle(root.children[1]);

// Toggle children.
function toggle(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
}

如您所见,d 与其 children 属性紧密耦合 - 我正在尝试重写此函数以接受 JSON 中的任何嵌套对象,以便它也可以可以切换/扩展。然而我还没有任何运气(用 hasOwnProperty 进行实验)。有什么想法吗?

编辑:包括我的 JSON 结构:

{
"date": "10242013"
"id": 34534
"addr": "444 Little Lane"
"department": {id: 13, addr: "555 ShoeHorse Road", name: "CTS",…}
"manager": {id: 454, addr: "444 Little Lane", name: "Bobby Johnson",…}
...

忽略类型错误的 JSON ^ 该对象可以有许多嵌套对象以及这些对象中的对象。我试图避免使用硬编码解决方案,而采用“:accept all”方法。

最佳答案

我已经编写了代码,将您的自定义 JSON 转换为 d3 Tree 布局所需的格式。

var json = {
"date": "10242013",
"id": "34534",
"addr": "444 Little Lane",
"department": {
"id": 13,
"addr": "555 ShoeHorse Road",
"name": "CTS",
"computer": {
"id": 56,
"name": "CT"
},
"electronics": {
"id": 65,
"name": "EC"
}
},
"manager": {
"id": 454,
"addr": "444 Little Lane",
"name": "Bobby Johnson"
}
};

function convertJSON(object) {
for (var key in object) {
if (typeof(object[key]) == "object") {
var obj = convertJSON(object[key]);
obj.key = obj.name ? obj.name : "";
obj.name = key;
if (!object["children"])
object["children"] = [];
object["children"].push(obj);
delete object[key];
}
}
return object;
}

json = convertJSON(json);

console.log(json);
var m = [20, 120, 20, 120],
w = 1280 - m[1] - m[3],
h = 800 - m[0] - m[2],
i = 0,
root;

var tree = d3.layout.tree()
.size([h, w]);

var diagonal = d3.svg.diagonal()
.projection(function(d) {
return [d.y, d.x];
});

var vis = d3.select("#body").append("svg:svg")
.attr("width", w + m[1] + m[3])
.attr("height", h + m[0] + m[2])
.append("svg:g")
.attr("transform", "translate(" + m[3] + "," + m[0] + ")");

root = json;
root.x0 = h / 2;
root.y0 = 0;

function toggleAll(d) {
if (d.children) {
d.children.forEach(toggleAll);
toggle(d);
}
}

// Initialize the display to show a few nodes.
root.children.forEach(toggleAll);

update(root);

function update(source) {
var duration = d3.event && d3.event.altKey ? 5000 : 500;

// Compute the new tree layout.
var nodes = tree.nodes(root).reverse();

// Normalize for fixed-depth.
nodes.forEach(function(d) {
d.y = d.depth * 180;
});

// Update the nodes…
var node = vis.selectAll("g.node")
.data(nodes, function(d) {
return d.id || (d.id = ++i);
});

// Enter any new nodes at the parent's previous position.
var nodeEnter = node.enter().append("svg:g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + source.y0 + "," + source.x0 + ")";
})
.on("click", function(d) {
toggle(d);
update(d);
});

nodeEnter.append("svg:circle")
.attr("r", 1e-6)
.style("fill", function(d) {
return d._children ? "lightsteelblue" : "#fff";
});

nodeEnter.append("svg:text")
.attr("x", function(d) {
return d.children || d._children ? -10 : 10;
})
.attr("dy", ".35em")
.attr("text-anchor", function(d) {
return d.children || d._children ? "end" : "start";
})
.text(function(d) {
return d.name;
})
.style("fill-opacity", 1e-6);

// Transition nodes to their new position.
var nodeUpdate = node.transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + d.y + "," + d.x + ")";
});

nodeUpdate.select("circle")
.attr("r", 4.5)
.style("fill", function(d) {
return d._children ? "lightsteelblue" : "#fff";
});

nodeUpdate.select("text")
.style("fill-opacity", 1);

// Transition exiting nodes to the parent's new position.
var nodeExit = node.exit().transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + source.y + "," + source.x + ")";
})
.remove();

nodeExit.select("circle")
.attr("r", 1e-6);

nodeExit.select("text")
.style("fill-opacity", 1e-6);

// Update the links…
var link = vis.selectAll("path.link")
.data(tree.links(nodes), function(d) {
return d.target.id;
});

// Enter any new links at the parent's previous position.
link.enter().insert("svg:path", "g")
.attr("class", "link")
.attr("d", function(d) {
var o = {
x: source.x0,
y: source.y0
};
return diagonal({
source: o,
target: o
});
})
.transition()
.duration(duration)
.attr("d", diagonal);

// Transition links to their new position.
link.transition()
.duration(duration)
.attr("d", diagonal);

// Transition exiting nodes to the parent's new position.
link.exit().transition()
.duration(duration)
.attr("d", function(d) {
var o = {
x: source.x,
y: source.y
};
return diagonal({
source: o,
target: o
});
})
.remove();

// Stash the old positions for transition.
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
}

// Toggle children.
function toggle(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
}
.node circle {
cursor: pointer;
fill: #fff;
stroke: steelblue;
stroke-width: 1.5px;
}
.node text {
font-size: 11px;
}
path.link {
fill: none;
stroke: #ccc;
stroke-width: 1.5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="body">
<div id="footer">
d3.layout.tree
<div class="hint">click or option-click to expand or collapse</div>
</div>
</div>

其他可能的方法是重写树形图的 children 函数,并迭代 d 并使用 tyepof 查找它是否是子元素或不。但这并不那么容易。

在这种情况下,toggle 方法可能如下所示。

function toggle(d) {
for(var key in d){
if (typeof(d[key])=="object") {
if((/^_/).test(key)){
d[key.substr(0)] = d[key];
} else{
d["_"+key] = d[key];
}
delete d[key];
}
}
}

关于javascript - 接受 D3 布局树中的通用嵌套对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33094771/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com