Public
Edited
Oct 30, 2023
Insert cell
Insert cell
nodes = [
{name: 'Jacqueline', familyName: 'Bouvier'},
{name: 'Clancy', familyName: 'Bouvier'},
{name: 'Mona', familyName: 'Simpson'},
{name: 'Abraham', familyName: 'Simpson'},
{name: 'Patty', familyName: 'Bouvier', parents: ['Jacqueline','Clancy']},
{name: 'Selma', familyName: 'Bouvier', parents: ['Jacqueline','Clancy']},
{name: 'Marge', familyName: 'Simpson', parents: ['Jacqueline','Clancy']},
{name: 'Homer', familyName: 'Simpson', parents: ['Mona','Abraham']},
{name: 'Lisa', familyName: 'Simpson', parents: ['Marge','Homer']},
{name: 'Bart', familyName: 'Simpson', parents: ['Marge','Homer']},
{name: 'Maggie', familyName: 'Simpson', parents: ['Marge','Homer']},
]
Insert cell
generations = [
[
{name: 'Parents', label: true},
{name: 'Jacqueline', familyName: 'Bouvier'},
{name: 'Clancy', familyName: 'Bouvier'},
],[
{name: 'Siblings', label: true},
{name: 'Selma', familyName: 'Bouvier', parents: ['Jacqueline','Clancy']},
{name: 'Patty', familyName: 'Bouvier', parents: ['Jacqueline','Clancy']},
{name: '', label: true},
{name: 'Marge', familyName: 'Simpson', parents: ['Jacqueline','Clancy'], selected: true},
{name: ' ', label: true},
{name: 'Partners', label: true},
{name: 'Homer', familyName: 'Simpson', parents: ['Mona','Abraham']},
],[
{name: 'Children', label: true},
{name: 'Lisa', familyName: 'Simpson', parents: ['Marge','Homer']},
{name: 'Bart', familyName: 'Simpson', parents: ['Marge','Homer']},
{name: 'Maggie', familyName: 'Simpson', parents: ['Marge','Homer']},
]
]
Insert cell
supino = [
[
//{name: 'Genitori', label: true},
{name: 'Davide', familyName: 'Supino'},
{name: 'Enrichetta', familyName: 'Gentiluomo', tomb: 584, birth: 1792, death: 1857},
],[
//{name: '', label: true},
{name: 'Moisè', familyName: 'Supino', parents: ['Davide','Enrichetta'], selected: true, tomb: 465, birth: 1813, death: 1878},
//{name: 'Partner', label: true},
//{name: ' ', label: true},
{name: 'Rachele', familyName: 'Rignano'},
{name: 'Ottavia', familyName: 'Levi', tomb: 464, birth: 1835, death: 1925},
],[
//{name: 'Figli', label: true},
{name: 'David', familyName: 'Supino', parents: ['Moisè','Rachele']},
{name: 'Vito', familyName: 'Supino', parents: ['Moisè','Rachele']},
{name: 'Vittorio', familyName: 'Supino', parents: ['Moisè','Rachele']},
{name: 'Ester', familyName: 'Supino', parents: ['Moisè','Rachele']},
{name: 'Isacco Igino Benvenuto', familyName: 'Supino', parents: ['Moisè','Ottavia'], tomb: 148, birth: 1858, death: 1940},
{name: 'Camillo', familyName: 'Supino', parents: ['Moisè','Ottavia']},
{name: 'Raffaello', familyName: 'Supino', parents: ['Moisè','Ottavia']},
{name: 'Felice Buonanno', familyName: 'Supino', parents: ['Moisè','Ottavia']},
]
]
Insert cell
new Tree(supino, {id: (d) => d.name})
.pipe(layout.x.naive, {distance: 75})
.pipe(layout.y.naive, {distance: 75})
.pipe(layout.links.naive)
.pipe(render, {min_width: 300, margin: 70, link_curve_radius: 16, node_text_dx: 0, node_text_dy: -16})
Insert cell
Insert cell
Insert cell
Insert cell
render = (tree, {min_width = 200, margin = 20, node_text_dx = 6, node_text_dy = -6, link_curve_radius = 10}={}) => {
return svg`<svg width="${Math.max(min_width, tree.properties.width+2*margin)}" height="${tree.properties.height+2*margin}" style="background: whitesmoke;">
<defs>
<style>
.node {
stroke: #AAA;
stroke-width: 3;
fill: white;
}
.link {
stroke: #9CE;
stroke-width: 3.5;
fill: none;
}
.node_text {
font-family: sans-serif;
font-size: 12px;
text-anchor: middle;
}
.node.placed {
stroke: black;
}
.node.selected {
fill: brown;
stroke: brown;
}
.node_text.selected {
font-weight: bold;
fill: brown;
}
.label {
font-family: sans-serif;
font-weight: bold;
font-size: 15px;
fill: gray;
}
.halo {
stroke: whitesmoke;
stroke-width: 3px;
}
.dates {
font-size: 10px;
font-style: italic;
}
</style>
</defs>
<g transform="translate(${margin},${margin})">
${tree.getLinks().map(d => `
<path class="link" d="${connectors.rounded({x: d.x1, y: d.y1}, {x: d.xc, y: d.yc}, {sweep: true, corner_radius: link_curve_radius})}"/>
<path class="link" d="${connectors.rounded({x: d.xc, y: d.yc}, {x: d.x2, y: d.y2}, {sweep: false, corner_radius: link_curve_radius})}"/>
`).join('')}
${tree.getNodes().filter(d => !d.label).map(d => `
<circle class="node${d.selected ? ' selected' : ''}${d.tomb ? ' placed' : ''}" cx="${d.x}" cy="${d.y}" r="10"/>
<text class="halo node_text${d.selected ? ' selected' : ''}" x="${d.x+node_text_dx}" y="${d.y+node_text_dy}">
<tspan>${d.name} ${d.familyName}</tspan>
${d.birth || d.death ? `<tspan class="dates" x="${d.x+node_text_dx}" dy="39px">${d.birth ? d.birth : '?'} — ${d.death ? d.death : '?'}</tspan>` : ''}
</text>
<text class="node_text${d.selected ? ' selected' : ''}" x="${d.x+node_text_dx}" y="${d.y+node_text_dy}">
<tspan>${d.name} ${d.familyName}</tspan>
${d.birth || d.death ? `<tspan class="dates" x="${d.x+node_text_dx}" dy="39px">${d.birth ? d.birth : '?'} — ${d.death ? d.death : '?'}</tspan>` : ''}
</text>
`).join('')}

${tree.getNodes().filter(d => d.label).map(d => `
<text class="halo label" x="${d.x+node_text_dx}" y="${d.y+3}">${d.name}</text>
<text class="label" x="${d.x+node_text_dx}" y="${d.y+3}">${d.name}</text>
`).join('')}
</g>
</svg>`
}
Insert cell
Insert cell
Insert cell
Graph = require('graphology')
Insert cell
GraphologyDag = import('https://cdn.skypack.dev/graphology-dag@0.3.0?min')
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