<div>
<style>
.tree{
width: 100%;
height: 100%;
}
.node {
cursor: pointer;
}
.node circle {
fill: #888;
}
.node text {
fill: #666;
font-size: 14px;
}
.node path {
fill: #fff;
stroke: #fff;
stroke-width: 0.2px;
}
.node0 circle {
fill: #aaceff;
stroke-opacity: 0.5;
stroke: #aaceff;
stroke-width: 8px;
}
.node1 circle {
fill: #fd9bb4;
stroke: #fd9bb4;
stroke-width: 6px;
}
.node2 circle {
fill: #af9ffc;
stroke: #af9ffc;
stroke-width: 6px;
}
.node3 circle {
fill: #9be4b7;
}
/*.node.node-child circle {
stroke-opacity: 0.5;
transform: scale(1.2);
}*/
.node:hover text {
fill: #333;
font-weight: bold;
font-size: 14px;
}
.node:hover circle {
transform: scale(1.2);
}
.node:not(.node3) text {
text-shadow: 0 1px 0 #fff, 0 -1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff;
}
.node0 text{
font-size: 16px!important;
}
.link {
fill: none;
stroke: #c6c6c6;
stroke-opacity: 0.4;
stroke-width: 1px;
}
body {
background-color: white
}
</style>
<script src="https://d3js.org/d3.v4.min.js"></script>
<div id="tree" class="tree"></div>
<script>
var tree, // d3
rootData, //
container, // svg
linkContainer, // link
nodeIndex = 0; // id
draw();
function draw() {
function getStyle(oElement, sName) { // IE
return oElement.currentStyle ? oElement.currentStyle[sName] : window.getComputedStyle(oElement, null)[sName];
}
tree = d3.tree()
.size([Math.PI * 2, 600])
.separation(function(a, b) { return (a.parent === b.parent ? 1 : 2) / a.depth });
var con = d3.select("#tree"),
width = parseInt(getStyle(con._groups[0][0], "width"), 10),
height = parseInt(getStyle(con._groups[0][0], "height"), 10),
svg = con.append("svg")
.attr("xmlns", "http://www.w3.org/2000/svg")
.attr("width", width)
.attr("height", height);
container = svg.append("g");
linkContainer = container.append("g");
// chrome
var zoom = d3.zoom()
.scaleExtent([0.4, 2])
.on("zoom", function() {
// v4: translate scale event.transform
// d3.event.transform
// "translate(" + d3.event.transform.x + "," + d3.event.transform.y ")scale(" + d3.event.transform.k + ")"
container.attr("transform", d3.event.transform);
});
svg.call(zoom);
//
svg.call(zoom.transform, d3.zoomIdentity.translate(width / 2, height / 2).scale(0.9));
getData();
}
function getData() {
d3.json("https://gist.githubusercontent.com/rykermorgan/bb3b38c5f3b0a8ac9b11d31eee2e3689/raw/18d78005069b3fef729f553ae122b63beefc1f0e/jm_family.json", function(error, data) {
if (error) throw error;
// d3
rootData = d3.hierarchy(data, function(d) { return d.children; });
rootData.children.forEach(collapse);
// Collapse the node and all it's children
function collapse(d) {
if(d.children) {
d._children = d.children;
d._children.forEach(collapse);
d.children = null;
}
}
drawTree(rootData);
});
}
//
function drawTree(source) {
/*
* @method radialPoint
* @param {Number} x
* @param {Number} y
* @return {Array}
*/
function radialPoint(x, y) {
return [(y = +y) * Math.cos(x -= Math.PI / 2), y * Math.sin(x)];
}
//
source.x0 = 3.141592653589793;
source.y0 = 0;
var treeData = tree(rootData); // Assigns the x and y position for the nodes
var nodes = treeData.descendants(); // Array
var links = treeData.links(); // Array
// Normalize for fixed-depth
nodes.forEach(function(d) {
if(d.depth === 1) {
d.y = d.depth * 180;
}else {
d.y = d.depth * 220;
}
});
var node = container.selectAll(".node")
.data(nodes, function(d) { // id
return d.id || (d.id = ++nodeIndex);
});
// Enter
var nodeEnter = node.enter().append("g")
.attr("class", function(d) {
return "node node" + d.depth;
})
.attr("transform", function(d) {
return "translate(" + radialPoint(source.x0, source.y0) + ")";
})
.on("click", function(d) {
if(d.depth > 0) toggle(d);
});
nodeEnter.append("circle")
.attr("r", 1e-6)
.style("stroke-opacity", function(d) {
if(d.children) {
return 0.5;
}else {
return 0;
}
});
nodeEnter.append("path")
.attr("d", function(d) {
if(d.depth > 0 && d._children) {
return "M-6 -1 H-1 V-6 H1 V-1 H6 V1 H1 V6 H-1 V1 H-6 Z";
}else if(d.depth > 0 && d.children) {
return "M-6 -1 H6 V1 H-6 Z";
}
})
.style("fill-opacity", 0);
nodeEnter.append("text")
.attr("dy", function(d) {
if(d.depth === 0) return "-1.5em";
return "0.31em";
})
.attr("x", function(d) {
if(d.depth === 0) return 0;
return d.x < Math.PI ? 16 : -16;
})
.attr("text-anchor", function(d) {
if(d.depth === 0) return "middle";
return d.x < Math.PI ? "start" : "end";
})
.attr("transform", function(d) {
if(d.depth === 0) return "rotate(0)";
return "rotate(" + (d.x < Math.PI ? d.x - Math.PI / 2 : d.x + Math.PI / 2) * 180 / Math.PI + ")";
})
.text(function(d) {
return d.data.name;
})
.style("fill-opacity", 1e-6);
// Update
var nodeUpdate = nodeEnter.merge(node).transition()
.duration(600)
.attr("transform", function(d) {
return "translate(" + radialPoint(d.x, d.y) + ")";
});
nodeUpdate.select("circle")
.attr("r", function(d) {
if(d.depth === 0) {
return 12;
}else if(d.depth < 3) {
return 10;
}
return 8;
})
.style("stroke-opacity", function(d) {
if(d.children) {
return 0.5;
}else {
return 0;
}
});
nodeUpdate.select("path")
.attr("d", function(d) {
if(d.depth > 0 && d._children) {
return "M-6 -1 H-1 V-6 H1 V-1 H6 V1 H1 V6 H-1 V1 H-6 Z";
}else if(d.depth > 0 && d.children) {
return "M-6 -1 H6 V1 H-6 Z";
}
})
.style("fill-opacity", 1);
nodeUpdate.select("text")
.attr("x", function(d) {
if(d.depth === 0) return 0;
return d.x < Math.PI ? 16 : -16;
})
.attr("text-anchor", function(d) {
if(d.depth === 0) return "middle";
return d.x < Math.PI ? "start" : "end";
})
.attr("transform", function(d) {
if(d.depth === 0) return "rotate(0)";
return "rotate(" + (d.x < Math.PI ? d.x - Math.PI / 2 : d.x + Math.PI / 2) * 180 / Math.PI + ")";
})
.style("fill-opacity", 1);
// Exit
var nodeExit = node.exit().transition()
.duration(600)
.attr("transform", function(d) {
return "translate(" + radialPoint(source.x, source.y) + ")";
})
.remove();
nodeExit.select("circle")
.attr("r", 1e-6);
nodeExit.select("path")
.style("fill-opacity", 0);
nodeExit.select("text")
.style("fill-opacity", 1e-6);
var link = linkContainer.selectAll(".link")
.data(links, function(d) { // node
return d.id || (d.id = "link" + d.source.id + d.target.id);
});
var linkRadial = d3.linkRadial();
var linkEnter = link.enter().append("path")
.attr("class", "link")
.attr("d", linkRadial
.angle(function(d) {
return source.x0;
})
.radius(function(d) {
return source.y0;
})
);
linkEnter.merge(link).transition()
.duration(600)
.attr("d", linkRadial
.angle(function(d) {
return d.x;
})
.radius(function(d) {
return d.y;
})
);
link.exit().transition()
.duration(600)
.attr("d", linkRadial
.angle(function(d) {
return source.x;
})
.radius(function(d) {
return source.y;
})
)
.remove();
// Store the old positions for transition.
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
}
function toggle(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
drawTree(d);
}
</script>
</div>
{
"name": "Jerry & Mona Park",
"parent": "null",
"size": 10,
"type": "steelblue",
"level": "red",
"children": [
{
"name": "James Morse Park",
"parent": "Jerry & Mona Park",
"size": 10,
"type": "purple",
"level": "purple",
"children": [
{
"name": "Sarah Elise Park",
"parent": "James Morse Park",
"size": 10,
"type": "steelblue",
"level": "red"
},
{
"name": "Leah Corinne Park",
"parent": "James Morse Park",
"size": 10,
"type": "steelblue",
"level": "red"
}
]
},
{
"name": "Cheryl Ann Park",
"parent": "Jerry & Mona Park",
"size": 10,
"type": "steelblue",
"level": "red",
"children": [
{
"name": "Justin Allen Sheeley",
"parent": "Cheryl Ann Park",
"size": 10,
"type": "steelblue",
"level": "red",
"children": [
{
"name": "Zane William Allen Sheeley",
"parent": "Justin Allen Sheeley",
"size": 10,
"type": "steelblue",
"level": "red"
}
]
},
{
"name": "Cassie Marie Sheeley",
"parent": "Cheryl Ann Park",
"size": 10,
"type": "steelblue",
"level": "red",
"children": [
{
"name": "Carter Lee Ammon",
"parent": "Cassie Marie Sheeley",
"size": 10,
"type": "steelblue",
"level": "red"
},
{
"name": "Remington Bennett",
"parent": "Cassie Marie Sheeley",
"size": 10,
"type": "steelblue",
"level": "red"
}
]
},
{
"name": "Trisha Lynn Sheeley",
"parent": "Cheryl Ann Park",
"size": 10,
"type": "steelblue",
"level": "red",
"children": [
{
"name": "Noah Simon",
"parent": "Trisha Lynn Sheeley",
"size": 10,
"type": "steelblue",
"level": "red"
}
]
}
]
},
{
"name": "Robert Eugene Park",
"parent": "Jerry & Mona Park",
"size": 10,
"type": "steelblue",
"level": "red",
"children": [
{
"name": "Brooke Whitnie Adams",
"parent": "Robert Eugene Park",
"size": 10,
"type": "steelblue",
"level": "red",
"children": [
{
"name": "Riley Mckenna Bernuy",
"parent": "Brooke Whitnie Adams",
"size": 10,
"type": "steelblue",
"level": "red"
},
{
"name": "Payson Gabriel Bernuy",
"parent": "Brooke Whitnie Adams",
"size": 10,
"type": "steelblue",
"level": "red"
},
{
"name": "Sydnie Isabel Bernuy",
"parent": "Brooke Whitnie Adams",
"size": 10,
"type": "steelblue",
"level": "red"
},
{
"name": "Kyson Mario Bernuy",
"parent": "Brooke Whitnie Adams",
"size": 10,
"type": "steelblue",
"level": "red"
}
]
},
{
"name": "Arial Jannelle Park",
"parent": "Robert Eugene Park",
"size": 10,
"type": "steelblue",
"level": "red"
},
{
"name": "Colbren Robert Park",
"parent": "Robert Eugene Park",
"size": 10,
"type": "steelblue",
"level": "red"
},
{
"name": "Alex Logan Park",
"parent": "Robert Eugene Park",
"size": 10,
"type": "steelblue",
"level": "red"
},
{
"name": "Jordan Nathaniel Park",
"parent": "Robert Eugene Park",
"size": 10,
"type": "steelblue",
"level": "red",
"children": [
{
"name": "Desmond Justin Park",
"parent": "Jordan Nathaniel Park",
"size": 10,
"type": "steelblue",
"level": "red"
}
]
},
{
"name": "Jacob Forrest Park",
"parent": "Robert Eugene Park",
"size": 10,
"type": "steelblue",
"level": "red"
}
]
},
{
"name": "Jolene Park",
"parent": "Jerry & Mona Park",
"size": 10,
"type": "steelblue",
"level": "red",
"children": [
{
"name": "Jacqueline Rae Morgan",
"parent": "Jolene Park",
"size": 10,
"type": "steelblue",
"level": "red",
"children": [
{
"name": "Mazer Ogden Palsson",
"parent": "Jacqueline Rae Morgan",
"size": 10,
"type": "steelblue",
"level": "red"
},
{
"name": "Alana Rebekah Palsson",
"parent": "Jacqueline Rae Morgan",
"size": 10,
"type": "steelblue",
"level": "red"
},
{
"name": "Manti Morgan Palsson",
"parent": "Jacqueline Rae Morgan",
"size": 10,
"type": "steelblue",
"level": "red"
},
{
"name": "Lydia Faith Palsson",
"parent": "Jacqueline Rae Morgan",
"size": 10,
"type": "steelblue",
"level": "red"
}
]
},
{
"name": "Ryker Thomas Morgan",
"parent": "Jolene Park",
"size": 10,
"type": "steelblue",
"level": "red",
"children": [
{
"name": "Oliver Thomas Morgan",
"parent": "Ryker Thomas Morgan",
"size": 10,
"type": "steelblue",
"level": "red"
},
{
"name": "Indie Lynn Morgan",
"parent": "Ryker Thomas Morgan",
"size": 10,
"type": "steelblue",
"level": "red"
},
{
"name": "Ari May Morgan",
"parent": "Ryker Thomas Morgan",
"size": 10,
"type": "steelblue",
"level": "red"
}
]
},
{
"name": "Katrina Morgan",
"parent": "Jolene Park",
"size": 10,
"type": "steelblue",
"level": "red",
"children": [
{
"name": "Suri Lorna Willett",
"parent": "Katrina Morgan",
"size": 10,
"type": "steelblue",
"level": "red"
},
{
"name": "Jett Tucker Willett",
"parent": "Katrina Morgan",
"size": 10,
"type": "steelblue",
"level": "red"
}
]
}
]
},
{
"name": "Samuel Frank Park",
"parent": "Jerry & Mona Park",
"size": 10,
"type": "steelblue",
"level": "red",
"children": [
{
"name": "Drusilla Dawn Park",
"parent": "Samuel Frank Park",
"size": 10,
"type": "steelblue",
"level": "red"
},
{
"name": "Zachary Michael Park",
"parent": "Samuel Frank Park",
"size": 10,
"type": "steelblue",
"level": "red"
},
{
"name": "MacKenzie Marie Park",
"parent": "Samuel Frank Park",
"size": 10,
"type": "steelblue",
"level": "red"
},
{
"name": "Peyton Nicole Park",
"parent": "Samuel Frank Park",
"size": 10,
"type": "steelblue",
"level": "red"
}
]
}
]
}