Last active
March 22, 2018 14:35
-
-
Save ttataryn/fc15a0eb2c65ef62ba6a7a77bc99ea39 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<style> | |
@import url(http://fonts.googleapis.com/css?family=Source+Code+Pro:400,600); | |
body {font-family: "Source Code Pro", Consolas, monaco, monospace; line-height: 160%; font-size: 14px; margin: 0; } | |
#tooltip { | |
color: #454545; | |
opacity: .9; | |
background: #eee; | |
padding: 5px; | |
border: none; | |
border-radius: 5px; | |
position: absolute; | |
z-index: 10; | |
visibility: hidden; | |
white-space: nowrap; | |
pointer-events: none; | |
} | |
#circle circle { | |
fill: none; | |
pointer-events: all; | |
} | |
path.group { | |
fill-opacity: .8; | |
} | |
path.chord { | |
fill-opacity: .8; | |
stroke: #000; | |
stroke-width: .25px; | |
} | |
#circle:hover path.fade { | |
display: none; | |
} | |
aside {padding: 20px;} | |
h1, h3 {font-size: 14px; font-weight: normal; padding-left: 40px;} | |
</style> | |
</head> | |
<body> | |
<section id="diagram"></section> | |
<div id="tooltip"></div> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.13/d3.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script> | |
<script src="mapper.js"></script> | |
<script> | |
//******************************************************************* | |
// CREATE MATRIX AND MAP | |
//******************************************************************* | |
d3.csv('gurus.csv', function (error, data) { | |
var mpr = chordMpr(data); | |
mpr | |
.addValuesToMap('source') | |
.addValuesToMap('target') | |
.setFilter(function (row, a, b) { | |
return (row.source === a.name && row.target === b.name) | |
}) | |
.setAccessor(function (recs, a, b) { | |
if (!recs[0]) return 0; | |
return +recs[0].value; | |
}); | |
drawChords(mpr.getMatrix(), mpr.getMap()); | |
}); | |
//******************************************************************* | |
// DRAW THE CHORD DIAGRAM | |
//******************************************************************* | |
function drawChords (matrix, mmap) { | |
var w = 1000, h = 900, r1 = h / 2.5, r0 = r1 - 100; | |
//change size of window and diagram | |
var fill = d3.scale.category10(); | |
colors = ["#301E1E", "#083E77", "#342350", "#567235", "#8B161C", "#C0C0C0", "#DF7C00", "#6A5ACD","#87CEEB","#A0522D","#FFF5EE","#C0C0C0"] | |
var colors = d3.scale.ordinal() | |
.domain(d3.range(10)) | |
.range(colors); | |
var chord = d3.layout.chord() | |
.padding(.1) | |
.sortSubgroups(d3.descending) | |
.sortChords(d3.descending); | |
var arc = d3.svg.arc() | |
.innerRadius(r0) | |
.outerRadius(r0 + 20); | |
var svg = d3.select("#diagram").append("svg") | |
.attr("width", w) | |
.attr("height", h) | |
.append("svg:g") | |
.attr("id", "circle") | |
.attr("transform", "translate(" + w / 1.8 + "," + h / 1.8 + ")"); | |
//change where on the screen it is | |
svg.append("circle") | |
.attr("r", r0 + 20); | |
var rdr = chordRdr(matrix, mmap); | |
chord.matrix(matrix); | |
var g = svg.selectAll("g.group") | |
.data(chord.groups()) | |
.enter().append("g") | |
.attr("class", "group") | |
.on("click", mouseover) | |
.on("mouseout", function (d) { d3.select("#tooltip").style("visibility", "hidden") }); | |
g.append("svg:path") | |
.style("fill", function(d) { return colors(d.index); }) | |
.attr("d", arc); | |
g.append("svg:text") | |
.each(function(d) { d.angle = (d.startAngle + d.endAngle) / 2; }) | |
.attr("dy", ".35em") | |
.attr("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; }) | |
.attr("transform", function(d) { | |
return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")" | |
+ "translate(" + (r0 + 26) + ")" | |
+ (d.angle > Math.PI ? "rotate(180)" : ""); | |
}) | |
.text(function(d) { return rdr(d).gname; }); | |
var chordPaths = svg.selectAll("path.chord") | |
.data(chord.chords()) | |
.enter().append("svg:path") | |
.attr("class", "chord") | |
.style("stroke", function(d) { return d3.rgb(colors(d.target.index)).darker(); }) | |
.style("fill", function(d) { return colors(d.target.index); }) | |
.attr("d", d3.svg.chord().radius(r0)) | |
.on("click", function (d) { | |
d3.select("#tooltip") | |
.style("visibility", "visible") | |
.html(chordTip(rdr(d))) | |
.style("top", function () { return (d3.event.pageY - 100)+"px"}) | |
.style("left", function () { return (d3.event.pageX - 100)+"px";}) | |
}) | |
.on("mouseout", function (d) { d3.select("#tooltip").style("visibility", "hidden") }); | |
function chordTip (d) { | |
var p = d3.format(".0%"), q = d3.format("0d") | |
return "Chord info:<br/>" | |
+ q(d.svalue) + " students work in " + d.sname + " and " + d.tname | |
} | |
function groupTip (d) { | |
var guru = d.gname, q = d3.format("0d"); | |
switch (guru) { | |
case "g1": return "Guru Nanak"; //+ " lived for 70 years"; | |
break; | |
case "g2": return "Guru Angad"; // + " lived for 48 years"; | |
break; | |
case "g3": return "Guru Amar Das"; // + " lived for 95 years"; | |
break; | |
case "g4": return "Guru Ram Das"; // + " lived for 47 years"; | |
break; | |
case "g5": return "Guru Arjun Dev"; // + " lived for 43 years"; | |
break; | |
case "g6": return "Guru Har Gobind"; // + " lived for 49 years"; | |
break; | |
case "g7": return "Guru Har Rai"; // + " lived for 31 years"; | |
break; | |
case "g8": return "Guru Har Krishan"; // + " lived for 8 years"; | |
break; | |
case "g9": return "Guru Tegh Bahadar"; // + " lived for 54 years"; | |
break; | |
case "g10": return "Guru Gobind Singh"; // + " lived for 42 years"; | |
break; | |
default : return d.gname; | |
} | |
} | |
function mouseover(d, i) { | |
d3.select("#tooltip") | |
.style("visibility", "visible") | |
.html(groupTip(rdr(d))) | |
.style("top", function () { return (d3.event.pageY - 80)+"px"}) | |
.style("left", function () { return (d3.event.pageX - 130)+"px";}) | |
chordPaths.classed("fade", function(p) { | |
return p.source.index != i | |
&& p.target.index != i; | |
}); | |
} | |
} | |
</script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//******************************************************************* | |
// CHORD MAPPER | |
//******************************************************************* | |
function chordMpr (data) { | |
var mpr = {}, mmap = {}, n = 0, | |
matrix = [], filter, accessor; | |
mpr.setFilter = function (fun) { | |
filter = fun; | |
return this; | |
}, | |
mpr.setAccessor = function (fun) { | |
accessor = fun; | |
return this; | |
}, | |
mpr.getMatrix = function () { | |
matrix = []; | |
_.each(mmap, function (a) { | |
if (!matrix[a.id]) matrix[a.id] = []; | |
_.each(mmap, function (b) { | |
var recs = _.filter(data, function (row) { | |
return filter(row, a, b); | |
}) | |
matrix[a.id][b.id] = accessor(recs, a, b); | |
}); | |
}); | |
return matrix; | |
}, | |
mpr.getMap = function () { | |
return mmap; | |
}, | |
mpr.printMatrix = function () { | |
_.each(matrix, function (elem) { | |
console.log(elem); | |
}) | |
}, | |
mpr.addToMap = function (value, info) { | |
if (!mmap[value]) { | |
mmap[value] = { name: value, id: n++, data: info } | |
} | |
}, | |
mpr.addValuesToMap = function (varName, info) { | |
var values = _.uniq(_.pluck(data, varName)); | |
_.map(values, function (v) { | |
if (!mmap[v]) { | |
mmap[v] = { name: v, id: n++, data: info } | |
} | |
}); | |
return this; | |
} | |
return mpr; | |
} | |
//******************************************************************* | |
// CHORD READER | |
//******************************************************************* | |
function chordRdr (matrix, mmap) { | |
return function (d) { | |
var i,j,s,t,g,m = {}; | |
if (d.source) { | |
i = d.source.index; j = d.target.index; | |
s = _.where(mmap, {id: i }); | |
t = _.where(mmap, {id: j }); | |
m.sname = s[0].name; | |
m.sdata = d.source.value; | |
m.svalue = +d.source.value; | |
m.stotal = _.reduce(matrix[i], function (k, n) { return k + n }, 0); | |
m.tname = t[0].name; | |
m.tdata = d.target.value; | |
m.tvalue = +d.target.value; | |
m.ttotal = _.reduce(matrix[j], function (k, n) { return k + n }, 0); | |
} else { | |
g = _.where(mmap, {id: d.index }); | |
m.gname = g[0].name; | |
m.gdata = g[0].data; | |
m.gvalue = d.value; | |
} | |
m.mtotal = _.reduce(matrix, function (m1, n1) { | |
return m1 + _.reduce(n1, function (m2, n2) { return m2 + n2}, 0); | |
}, 0); | |
return m; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment