2015-10-27 28 views
1

我需要創建四個獨立目標的旭日形圖。每個目標都有一個指定的顏色和所有目標的孩子應該繼承的顏色。我已經設置好讓孩子們接受他們父母的顏色,並且工作得很好。這個問題是一個孩子的孩子不繼承父最初的顏色。如何獲得相應的從D3旭日父顏色到最終的孩子呢?

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

回答

2

用於從得到的顏色你確定節點的名稱邏輯規模是有缺陷的:

(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); }) 

根據您的數據,並在此邏輯將如何經常會被稱爲量,你可能要考慮爲您的整個樹一旦這樣做,並存儲每個節點上的rootmost父母的名字。

+0

感謝這工作很好。 – jgrooms