Improving the D3 Sequence Sunburst Example

This D3 example served as a starting point:

http://bl.ocks.org/kerryrodden/7090426

enter image description here


I wanted to change the data that feeds the chart, and I made the following new example :

http://jsfiddle.net/ZGVK3/

enter image description here

You can notice at least two problems:

  • The legend is wrong. This is because it still contains the “hard-coded” names from the original example.
  • All nodes are painted black. This is because the color scheme is also “hard-coded” only for the node names from the original example.

How to improve the original example (or my jsfiddle, it doesn't matter) so that the legend and coloring are self-tuning for the data that feeds the chart?

+6
source share
1 answer

You can use ordinal scale to match colors with different node names. Implementing this will require only minor changes to existing code.

Step 1. Create an ordinal scale for the colors

Instead of colors being just a list of color names hardcoded for specific names, use d3.scale.ordinal() and set .range() be the array of colors you want to use. For instance:

 var colors = d3.scale.ordinal() .range(["#5687d1","#7b615c","#de783b","#6ab975","#a173d1","#bbbbbb"]); 

This will create an ordinal scale that uses the same colors as the original render. Since your data will require more colors, you would like to add a few more to your range, otherwise the colors will repeat.

You can use d3.scale.category20() as a shortcut so that d3 d3.scale.category20() range of 20 categorical colors for you.

Now that you set the fill colors for your path arcs, as well as your breadcrumbs, you simply use colors(d.name) instead of colors[d.name] .

Step 2. Use your data to build a scale domain

.domain() this scale will be set after we receive the data, as this will depend on the list of unique names contained in the data. To do this, we can scroll through the data and create an array of unique names. There are probably several ways to do this, but it works well here:

 var uniqueNames = (function(a) { var output = []; a.forEach(function(d) { if (output.indexOf(d.name) === -1) { output.push(d.name); } }); return output; })(nodes); 

This creates an empty array, then loops through each element of the nodes array, and if the name node does not yet exist in the new array, it is added.

Then you can simply set the new array as the color bar area:

 colors.domain(uniqueNames); 

Step 3. Use a scale domain to create a legend

Since the legend will depend on the domain, make sure that the drawLegend() function is called after the domain is installed.

You can find the number of elements in the domain (to set the legend height) by calling colors.domain().length . Then for the .data() legend, you can use the domain itself. Finally, to set the fill color for the legend fields, you call up the color scale on d , since each element in the domain is name . Here, these three changes to the legend look in practice:

 var legend = d3.select("#legend").append("svg:svg") .attr("width", li.w) .attr("height", colors.domain().length * (li.h + li.s)); var g = legend.selectAll("g") .data(colors.domain()) .enter().append("svg:g") .attr("transform", function(d, i) { return "translate(0," + i * (li.h + li.s) + ")"; }); g.append("svg:rect") .attr("rx", li.r) .attr("ry", li.r) .attr("width", li.w) .attr("height", li.h) .style("fill", function(d) { return colors(d); }); 

And about that. Hope this helps.

Here updated JSFiddle .

+10
source

Source: https://habr.com/ru/post/971785/


All Articles