Skip to content

Instantly share code, notes, and snippets.

@mell0kat
Created March 2, 2018 19:27
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mell0kat/5cb91a2048384560dfa8f041fd9a0295 to your computer and use it in GitHub Desktop.
Save mell0kat/5cb91a2048384560dfa8f041fd9a0295 to your computer and use it in GitHub Desktop.
d3.tree - A Family Tree
license: mit

Built with blockbuilder.org

d3.tree - A Family Tree

This graph is based on Mike Bostock's block converted to d3 v4

What I've learnt

  • d3.hierarchy() constructs a root node from given hierarchal (json) data

  • nodes have .descendants() method as well as .links() which have a source and target object

  • d3.tree() assigns a .x and .y (which are arbitrary, could be used for angle and radius) to the root node and its decendants

  • for svg elements, x and y are absolute coords while dx and dy are relative coords

  • dx and dy use 'em's are are good for centering things

  • can add multiple classes be simply space separating

    • e.g .attr('class', 'about location')
<!DOCTYPE html>
<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; }
text {
font-family: "Helvetica Neue", Helvetica, sans-serif;
}
.title {
font-size: larger;
text-align: center;
}
.name {
font-weight: bold;
}
.about {
fill: #777;
font-size: smaller;
}
.lifespan {
fill: #2c5;
}
.link {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.node {
fill: blue;
}
</style>
</head>
<body>
<script>
const margin = { top: 0, right: 320, bottom: 0, left: 0 }
const fullWidth = 960
const fullHeight = 500
const width = fullWidth - margin.left - margin.right
const height = fullHeight - margin.top - margin.bottom
const tree = d3.tree()
.separation((a, b) => ((a.parent === b.parent) ? 1 : 0.5))
.size([height, width])
const svg = d3.select('body')
.append('svg')
.attr('width', fullWidth)
.attr('height', fullHeight)
const g = svg.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`)
g.append('text')
.text('d3.tree - A Family Tree')
.attr('class', 'title')
.attr('x', 50)
.attr('y', 50)
const elbow = (d, i) => {
return `M${d.source.y},${d.source.x}H${d.target.y},V${d.target.x}${d.target.children ? '' : 'h' + margin.right}`
}
d3.json('tree.json', (err, json) => {
if (err) throw err
const nodes = d3.hierarchy(json, (d) => d.parents)
// maps hierarchy to tree layout
const treeNodes = tree(nodes)
// adds links between nodes
const link = g.selectAll('.link')
.data(treeNodes.links())
.enter().append('path')
.attr('class', 'link')
.attr('d', elbow)
const node = g.selectAll('.node')
.data(treeNodes.descendants())
.enter().append('g')
.attr('class', 'node')
.attr( 'transform', d => `translate(${d.y},${d.x})`)
node.append('text')
.attr('class', 'name')
.attr('x', 8)
.attr('y', -6)
.text(d => `${d.data.name}`)
node.append('text')
.attr('x', 8)
.attr('y', 8)
.attr('dy', '.71em')
.attr('class', 'about lifespan')
.text(d => `${d.data.born} - ${d.data.died}`)
node.append('text')
.attr('class', 'about location')
.attr('x', 8)
.attr('y', 8)
.attr('dy', '1.86em')
.text(d => `${d.data.location}`)
})
</script>
</body>
{
"name": "Clifford Shanks",
"born": 1862,
"died": 1906,
"location": "Petersburg, VA",
"parents": [
{
"name": "James Shanks",
"born": 1831,
"died": 1884,
"location": "Petersburg, VA",
"parents": [
{
"name": "Robert Shanks",
"born": 1781,
"died": 1871,
"location": "Ireland/Petersburg, VA"
},
{
"name": "Elizabeth Shanks",
"born": 1795,
"died": 1871,
"location": "Ireland/Petersburg, VA"
}
]
},
{
"name": "Ann Emily Brown",
"born": 1826,
"died": 1866,
"location": "Brunswick/Petersburg, VA",
"parents": [
{
"name": "Henry Brown",
"born": 1792,
"died": 1845,
"location": "Montgomery, NC"
},
{
"name": "Sarah Houchins",
"born": 1793,
"died": 1882,
"location": "Montgomery, NC"
}
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment