Built with blockbuilder.org
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"/>
<link href='https://fonts.googleapis.com/css?family=Raleway:100,300' rel='stylesheet' type='text/css'>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/susielu/d3-annotation/d3-annotation.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.7.1/d3-tip.min.js"></script>
<style>
body {
background: black;
font-family: raleway;
}
h1 {
color: white;
}
.node circle {
fill: #999;
opacity: 0.8;
}
.node text {
font: 10px sans-serif;
opacity: 0.8;
}
.node--internal circle {
fill: #555;
}
.node--internal text {
}
.link {
fill: none;
stroke: white;
stroke-opacity: 0.8;
stroke-width: 1.5px;
}
.annotation path {
stroke: white;
fill: none;
}
.annotation path
.connector-arrow,
.title text,
.annotation text,
.annotation.callout.circle
.annotation-subject path {
fill: white;
}
.annotation-note-bg {
fill: white;
}
.annotation-note-title {
font-family: Lato;
font-weight: bold;
font-size: 16px;
}
.annotation.xythreshold {
cursor: move;
}
.hidden {
display: none;
}
text.hover {
font-size: .7em;
}
text.title {
font-size: 1.1em;
}
</style>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-xs-12 text-center">
<h1>HOW I MET MY FRIENDS<h1>
</div>
</div>
<div class="row">
<div class="col-xs-12 chart text-center">
</div>
</div>
<br>
</div>
<script>
//set width, height, and append svg
var margin = { top: 20, right: 20, bottom: 20, left: 20};
var width = 960 - margin.left - margin.right; //1200-20-20 = 1160
var height = 900 - margin.top - margin.bottom; //900-20-20 = 860
var fontSize = [24,9,9,9, 9];
var svg = d3.select('.chart')
.append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom)
.attr("transform", "translate(" + -120 + "," + 0 + ")");
//append group element to svg
var g = svg.append("g")
.attr('width', width)
.attr('height', height)
.attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")");
//append separate groups for the visualization and the legend to the group element
var gViz = g.append("g")
.attr("class", "vizualization")
.attr("transform", "translate(0, -70)");
var gLegend = g.append("g")
.attr("class", "legend")
.attr('width', width)
.attr('height', height)
.attr("transform", "translate(-1300, -400)");
//create the color scale
var color = d3.scaleOrdinal()
.range(d3.schemePaired
.map(function(d) { c = d3.rgb(d); c.opacity = 0.9; return d; }));
//stratify data and make it into the tree format
var stratify = d3.stratify()
.parentId(function(d) { return d.id.substring(0, d.id.lastIndexOf(".")); });
var tree = d3.tree()
.size([2 * Math.PI, 500])
.separation(function(a, b) { return (a.parent == b.parent ? 1 : 2) / a.depth; });
//load csv
d3.csv("friends2.csv", function(error, flatData) {
if (error) throw error;
var root = tree(stratify(flatData));
//create links
var link = gViz.selectAll(".link")
.data(root.links())
.enter().append("path")
.attr("class", "link")
.attr("d", d3.linkRadial()
.angle(function(d) { return d.x; })
.radius(function(d) { return d.y; }))
.style("stroke", function(d) {var activity = d.target.id.split(".")[1]; return color(activity); });
//create node placeholders and append data
var node = gViz.selectAll(".node")
.data(root.descendants())
.enter().append("g")
.attr("transform", function(d) {return "translate(" + radialPoint(d.x, d.y) + ")"; });
node.append("circle")
.attr("r", 3)
.style("fill", function(d) {while (d.depth > 1) d = d.parent; return color(d.id.split(".")[1]); });
//append labels to viz
node.append("text")
.attr("dy", "0.31em")
.attr("x", function(d) { return d.x < Math.PI === !d.children ? 6 : -6; })
.attr("text-anchor", function (d){
if(d.height === 0){ return (d.x > Math.PI) ? "end" : "start"; }
else if(d.height === 1) {return d.x < Math.PI === !d.children ? "start" : "end";}
else { return "middle"; } })
.attr("dx", function (d){
if(d.depth === 3){ return (d.x > Math.PI) ? "-2px" : "2px"; }
else { return "0px"; } })
.attr("transform", function(d) { return "rotate(" + textRotation(d) + ")" })
.text(function(d) { if(d.depth != 1) return d.id.substring(d.id.lastIndexOf(".") + 1); })
.attr("font-size", function (d){ return fontSize[d.depth] + "pt"; })
.style("fill", function(d) { while (d.id === 'me') return 'white'; while (d.depth > 1) d = d.parent; return color(d.id.split(".")[1]); })
.classed("glow", function (d){return d.height !== 5; });
//create legend
var legend = gLegend.selectAll("g")
.data(root.children)
.enter().append("g")
.attr("transform", function(d, i) { return "translate(" + i * 80 + "," + 0 + ")"; });
legend.append("circle")
.attr("cx", width - 20)
.attr("cy", 9.5)
.attr("r", 5)
.style("fill", function(d) {var activity = d.id.split(".")[1]; return color(activity);});
legend.append("text")
.attr("x", width - 10)
.attr("y", 9.5)
.attr("dy", "0.32em")
.attr("font-family", "Raleway")
.attr("font-size", 12)
.attr("text-anchor", "right")
.text(function(d) { return d.id.split(".")[1]; })
.style("fill", function(d) {var activity = d.id.split(".")[1]; return color(activity); });
});
//create the text rotation
function textRotation(d) {
var angle = d.x / Math.PI * 180 + 90;
if (d.depth < 2) { return 0;}
else if (angle <= 270) { return angle - 180;}
else { return angle;}
}
function radialPoint(x, y) {
return [(y = +y) * Math.cos(x -= Math.PI / 2), y * Math.sin(x)];
}
//annotations
const labels = [
{
data: { Title: "Pierre", Story: "In-between graduate school and starting a full-time job, I started a private chef business and posted an add on Craigslist (circa 2007). Pierre was my first (and one of two) clients. After email exchanges post-meal-pick-up about Tuescany food and a pan “mix up,” he invited me to the symphony.... We eventually became friends." },
x: 123,
y: -157,
dx: 250,
dy: 70,
},
{
data: { Title: "Jessica", Story: "Jessica and I met in the elevator leaving a Meetup. We discovered we lived in the same neighborhood and she offered to share her Lyft with me. During the extra long ride (driver got lost), we chatted; we both love dancing, data, and maps. I then accompanied her on an impromptu scavenge to steal a construction sign across the street from her house. Our friendship was forever solidified." },
x: 105,
y: -169,
dx: 250,
dy: 10
},
{
data: { Title: "Claudine O.", Story: "Claudine O. and I met in Honduras when I was 19. She is the reason I live in California." },
x: -74,
y: 185,
dy: -50,
dx: -250
}].map(function (l) {l.note = Object.assign({},
l.note, { title: "" + l.data.Title, label: "" + l.data.Story });
l.subject = { radius: 6 };
return l;
});
window.makeAnnotations = d3.annotation()
.annotations(labels)
.type(d3.annotationCalloutCircle)
.on('subjectover', function (annotation) { annotation.type.a.selectAll("g.annotation-connector, g.annotation-note")
.classed("hidden", false); })
.on('subjectout', function (annotation) { annotation.type.a.selectAll("g.annotation-connector, g.annotation-note")
.classed("hidden", true); });
gViz.append("g")
.attr("class", "annotation-test")
.call(makeAnnotations);
gViz.selectAll("g.annotation-connector, g.annotation-note")
.classed("hidden", true);
</script>
</body>
Updated missing url https://rawgit.com/susielu/d3-annotation/master/d3-annotation.min.js to https://cdn.jsdelivr.net/gh/susielu/d3-annotation/d3-annotation.min.js
https://d3js.org/d3.v4.min.js
https://d3js.org/d3-scale-chromatic.v1.min.js
https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js
https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js
https://rawgit.com/susielu/d3-annotation/master/d3-annotation.min.js
https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.7.1/d3-tip.min.js