如何从d3森伯斯特父母到最终孩子获得相应的颜色?

时间:2015-10-27 14:50:24

标签: javascript json d3.js

我需要创建一个包含四个独立目标的旭日形图。每个目标都有一个指定的颜色,所有目标的孩子都应该继承该颜色。我设置它,以便孩子们采取父母的颜色,这是正常的。问题是孩子的孩子不会继承初始父母的颜色。

Sunburst screenshot

这是我用来创建可视化的代码:

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 }
                    ]
                }
             ]
          }
      ]
};
};

1 个答案:

答案 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); })

根据您的数据量以及调用此逻辑的频率,您可能需要考虑对整个树执行一次此操作,并在每个节点上存储最根本的父级名称。