I'm working on building a treemap in d3 v5 based on this example: https://www.d3indepth.com/layouts/
I can use the score
data point for the color scale on the lowest level children, but I'd like the parents of the boxes above to have an average of the children below.
A sample of my data is here:
{
"name": "Unit",
"children": [
{
"name": "SBU",
"children": [
{
"name": "App",
"value": 3000,
"score": 0.5
},
{
"name": "App",
"value": 3500,
"score": 0.1
},
{
"name": "App",
"value": 2000,
"score": 0.9
}
]
}
Code below:
d3.json("health.json").then(function(data) {
console.log(data)
var treemapLayout = d3.treemap()
.size([1700, 1500])
.paddingOuter(16);
var rootNode = d3.hierarchy(data)
// Determine the size and placement of the boxes
rootNode
.sum(function(d) { return d.value; })
.sort(function(a,b) { return b.value - a.value; });
treemapLayout(rootNode);
var nodes = d3.select('svg g')
.selectAll('g')
.data(rootNode.descendants())
.enter()
.append('g')
.attr('transform', function(d) {return 'translate(' + [d.x0, d.y0] + ')'})
nodes
.append('rect')
.attr('width', function(d) { return d.x1 - d.x0; })
.attr('height', function(d) { return d.y1 - d.y0; })
.attr('style', function(d) {
return ('fill:' + d3.interpolateRdYlGn(d.data.health))
})
nodes
.append('text')
.attr('dx', 4)
.attr('dy', 14)
.text(function(d) {
return d.data.name;
})
});
One way you could do it is to preprocess the data to include the parent nodes' average child score, and the color for each node:
Calculate the average child score for each of the parent nodes, and add the result to your data-structure.
{
"name": "SBU",
"avgScore": 0.5,
"children: [
Use a sequential scale to map these average results to a particular color in e.g. d3.interpolateRdYlGn, and add the result to the data:
const colorScale = d3.scaleSequential(d3.interpolateRdYlGn)
.domain([0, 1]); // depending on your data
const nodeColor = colorScale(data.parent.avgScore);
{
"name": "SBU",
"avgScore": 0.5,
"nodeColor": nodeColor
}
You could then assign specific colors to the data for the root and child nodes:
const childNodeColor = rgb(100, 200, 100);
{
// Child node
...,
nodeColor: childNodeColor
}
Then simply render the color for each node in your tree using:
...
.attr('style', function(d) {
return colorScale(d.nodeColor);
});