A test block visualising quantity of records from DigitalNZ partners and primary collections.
forked from fogonwater's block: Building a hierarchy from a flat table
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
</style>
</head>
<meta charset="utf-8">
<style>
body {text-align:center; font-family: sans-serif;}
svg { overflow:visible;}
</style>
<body>
<h1>dnz tree viz</h1>
<svg width="800" height="3000"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
console.clear()
const svg = d3.select("svg"),
width = +svg.attr("width"),
height= +svg.attr("height"),
margin= 20,
formatComma = d3.format(",")
// Set up a size scale
const radius = d3.scaleLinear()
.range( [0.5, 50])
.domain([1,10000000])
.clamp(true)
// Declare a D3 layout
const tree = d3.tree()
.size([height, width * 0.8])
// Load our external data
d3.csv("data.csv", function(data) {
data.sort(function(x, y){
return d3.descending(+x.count, +y.count);
})
// Build our hierarchy from a series of levels
// change/reorder the level elements for a different tree
const levels = ["cat", "content_partner"],
hierarchy = flatToHierarchy(data, levels, 'primary_collection', 'count'),
nodes = hierarchy.descendants(),
leaves=hierarchy.leaves(),
links = tree(hierarchy).links()
// Draw on screen
svg.selectAll('path')
.data(links)
.enter().append('path')
.attr('d', d3.linkHorizontal()
.x(function(d) { return d.y; })
.y(function(d) { return d.x; }))
.style('fill', 'none')
.style('opacity', 0.5)
.style('stroke', '#aaa')
.style('stroke-width',(d) => radius(d.target.value) * 2)
svg.selectAll('circle')
.data(nodes)
.enter().append('circle')
.style('r', (d) => radius(d.value))
.style('fill', 'white')
.style('stroke', '#444')
.style('stroke-width',1)
// TODO - make clearer
.attr('transform', function (d) {
return 'translate(' + d.y + ',' + d.x + ')'
})
svg.selectAll(".labels")
.data(nodes)
.enter().append("text")
.attr('text-anchor', 'start')
//.attr('ignore', function(d) {console.log(d.data); return ''})
.text((d) => d.depth == 3 ? d.data.name + ' (' + formatComma(d.data.count) + ')' : d.data.name)
.attr('font-size', '8px')
.attr('transform', function (d) {
return 'translate(' + (d.y + 3) + ',' + (d.x + 2) + ')'
})
})
// Helper function for converting flat data to a hierarchy
// with a name and count field on each node.
// TODO - probably shouldn't name the value field "count"
function flatToHierarchy(flatData, levels, nameField, countField) {
// Adapted from https://stackoverflow.com/a/19317823
var nestedData = { name :"root", children : [] }
// For each data row, loop through the expected levels traversing the output tree
flatData.forEach(function(d){
// Keep this as a reference to the current level
var depthCursor = nestedData.children;
// Go down one level at a time
levels.forEach(function( property, depth ){
// See if a branch has already been created
var index;
depthCursor.forEach(function(child,i){
if ( d[property] == child.name ) index = i;
});
// Add a branch if it isn't there
if ( isNaN(index) ) {
depthCursor.push({ name : d[property], children : []});
index = depthCursor.length - 1;
}
// Reference the new child array as we go deeper into the tree
depthCursor = depthCursor[index].children;
// This is a leaf, so add last element to specified branch
if ( depth === levels.length - 1 ) {
depthCursor.push({
'name':d[nameField],
'count':+d[countField]
});
}
})
})
// sum up the leaves / branches and return the hierarchy
return d3.hierarchy(nestedData).sum(function(d){ return d.count; })
}
</script>
</body>
</html>
https://d3js.org/d3.v4.min.js
https://d3js.org/d3.v4.min.js