我需要创建一个包含四个独立目标的旭日形图。每个目标都有一个指定的颜色,所有目标的孩子都应该继承该颜色。我设置它,以便孩子们采取父母的颜色,这是正常的。问题是孩子的孩子不会继承初始父母的颜色。
这是我用来创建可视化的代码:
var colors = d3.scale.ordinal()
.range(["#62ADDB", "#7568BA", "#FF8F2B", "#6BC96D"]);
var json = getData();
createVisualization(json);
// Main function to draw and set up the visualization, once we have the data.
function createVisualization(json) {
// Basic setup of page elements.
initializeBreadcrumbTrail();
d3.select("#togglelegend").on("click", toggleLegend);
// Bounding circle underneath the sunburst, to make it easier to detect
// when the mouse leaves the parent g.
vis.append("svg:circle")
.attr("r", radius)
.style("opacity", 0);
// For efficiency, filter nodes to keep only those large enough to see.
var nodes = partition.nodes(json)
.filter(function (d) {
return (d.dx > 0.005); // 0.005 radians = 0.29 degrees
});
var uniqueNames = (function (a) {
var output = [];
a.forEach(function (d) {
if (output.indexOf(d.name) === -1) {
output.push(d.name);
}
});
return output;
})(nodes);
// set domain of colors scale based on data
colors.domain(uniqueNames);
// make sure this is done after setting the domain
drawLegend();
var path = vis.data([json]).selectAll("path")
.data(nodes)
.enter().append("svg:path")
.attr("display", function (d) { return d.depth ? null : "none"; })
.attr("d", arc)
.attr("fill-rule", "evenodd")
.style("fill", function (d) { return colors((d.children ? d : d.parent).name); })
.style("opacity", 1)
.on("mouseover", mouseover);
// Add the mouseleave handler to the bounding circle.
d3.select("#container").on("mouseleave", mouseleave);
// Get total size of the tree = value of root node from partition.
totalSize = path.node().__data__.value;
};
function getData() {
return {
"name": "ref",
"children": [
{ "name": "EPIC",
"children": [
{ "name": "EPIC-a1", "size": 3 },
{ "name": "EPIC-a2", "size": 3 }
]
},
{ "name": "AD",
"children": [
{ "name": "AD-a1", "size": 3 },
{ "name": "AD-a2", "size": 3 }
]
},
{ "name": "SAP",
"children": [
{ "name": "SAP-a1", "size": 3 },
{ "name": "SAP-a2", "size": 3 }
]
},
{ "name": "Oracle",
"children": [
{ "name": "Oracle-a1", "size": 3 },
{ "name": "Oracle-a2", "size": 3,
"children": [
{ "name": "EPIC-b1", "size": 3 },
{ "name": "EPIC-b2", "size": 3 }
]
}
]
}
]
};
};
答案 0 :(得分:3)
您确定用于从比例尺中获取颜色的节点名称的逻辑存在缺陷:
(d.children ? d : d.parent).name
转换为:
如果我有孩子,请使用我的名字,如果我没有孩子,请使用我父母的名字。
然而,这不是你想要的。您正在寻找
给我一个最接近根的祖先的名字而不是根本身。
有多种方法可以实现这种逻辑:
<强> 1。通过递归
在我看来,这是实现目标的最优雅方式。
function getRootmostAncestorByRecursion(node) {
return node.depth > 1 ? getRootmostAncestorByRecursion(node.parent) : node;
}
<强> 2。通过迭代
您也可以使用JavaScript已知的各种循环来应用各种迭代。
function getRootmostAncestorByWhileLoop(node) {
while (node.depth > 1) node = node.parent;
return node;
}
对这两个函数之一的调用将取代上面提到的错误陈述。
.style("fill", function (d) { return colors(getRootmostAncestorByRecursion(d).name); })
根据您的数据量以及调用此逻辑的频率,您可能需要考虑对整个树执行一次此操作,并在每个节点上存储最根本的父级名称。