Published
Edited
Sep 7, 2020
Insert cell
Insert cell
chart = {
console.log('root', root)
const nodeSize = 16
const nodes = root.descendants()
console.log('nodes', nodes)
const links = root.links()
console.log('links', links)
const svg = d3.create('svg')
.attr('viewBox', [
-nodeSize / 2,
-nodeSize * 3 / 2,
width,
(nodes.length + 1) * nodeSize
])
.attr('font-family', 'sans-serif')
.attr('font-size', 10)
.style('overflow', 'visible');
// Create top-level SVG element
const link = svg.append('g')
.attr('fill', 'none')
.attr('stroke', '#999')
.selectAll('path')
.data(links)
.join('path')
.attr('d', d => `
M${d.source.depth * nodeSize},${d.source.index * nodeSize}
V${d.target.index * nodeSize}
h${nodeSize}
`);
// A `<g>` for each data item
const gNode = svg.append('g')
.selectAll('g')
.data(nodes) // binds data to nodes that don’t exist yet (!)
.join('g') // attaches a `g` for each datum
.attr('transform', d => `translate(0,${d.index * nodeSize})`);
// Because we just generated a group of elements,
// `gNode` is now a *group* of elements (but not an array!).
// Add the circle
gNode.append('circle')
.attr('cx', d => d.depth * nodeSize)
.attr('r', 2.5)
.attr('fill', d => d.children ? null : '#999');
// Add the text
gNode.append('text')
.attr('dy', '0.32em')
.attr('x', d => d.depth * nodeSize + 6)
.text(d => d.data.data ? d.data.data.Name : d.data.Name);
// Add the title
gNode.append('title')
.text(d => d.ancestors()
.reverse()
.map(d => d.data.data ? d.data.data.Name : d.data.Name)
.join('/')
);
console.debug('root.copy().descendants()', root.copy().descendants())

for (const {label, value, x} of columns) {
// add label headings at top
let svgColumnLabel = svg.append('text')
.attr('dy', '0.32em')
.attr('y', -nodeSize)
.attr('x', x)
.attr('font-weight', 'bold')
.text(label);
// add data for each gNode
let svgColumnData = gNode.append('text')
.attr('dy', '0.32em')
.attr('x', x)
.data(root.copy().descendants())
.text(d => value(d) );
// set the first column to right-aligned text
if (label == '# Children') {
svgColumnLabel.attr('text-anchor','end')
svgColumnData.attr('text-anchor','end')
}
}

return svg.node();
}
Insert cell
columns = [
{
label: "# Children",
value: d => {
return (d.data && d.data.data && d.data.data.children)
? d.data.data.children.length
: (d.data && d.data.children)
? d.data.children.length
: ''
}
,
x: 280
},
{
label: "Tags",
value: d => {
return (d.data && d.data.Tags)
? d.data.Tags
: (d.data.data && d.data.data.Tags)
? d.data.data.Tags
: ''
},
x: 300
}
]
Insert cell
Insert cell
Insert cell
Insert cell
root = {
let i = 0;
let root = d3.hierarchy(stratifiedData)
.eachBefore(d => d.index = i++)
// De-nest the redundant top-level `data`
Object.assign(root.data, root.data.data)
delete root.data.data
return root
}
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more