Skip to content

Instantly share code, notes, and snippets.

@katemonkeys
Last active August 29, 2015 14:02
Show Gist options
  • Save katemonkeys/8fe7ec1a3a0f7bd62098 to your computer and use it in GitHub Desktop.
Save katemonkeys/8fe7ec1a3a0f7bd62098 to your computer and use it in GitHub Desktop.
Lunch Money Debts This Quarter
node_modules/
This plot shows the total money owed between colleagues for lunch over time. Colors and chords indicate direction and amount of lending.
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<div id="ticker">March 1</div>
<div id="evolution">
</div>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"> </script>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>var color = d3.scale.category10();</script>
<script>
var names = ["Alex","Lauren","Ryan","Liz","Philip","Chris"]
var lunchData = [
[0,1,1,1,1,1],
[1,0,1,1,1,1],
[1,1,0,1,1,1],
[1,1,1,0,1,1],
[1,1,1,1,0,1],
[1,1,1,1,1,0]
];
var datafile = 'sequence.json';
d3.chart = d3.chart || {};
d3.chart.chord = function(options) {
var self = {};
var svg;
var chord = d3.layout.chord()
.padding(.05)
.sortSubgroups(d3.descending);
var w = Math.min(screen.width,960)-20,
h = Math.min(screen.height,500),
innerRadius, outerRadius,
coloring = 'bigger';
if (screen.width<screen.height) {
innerRadius = w * .30;
} else {
innerRadius = h * .37;
}
outerRadius = innerRadius * 1.1;
self.fill = color;
var arc_svg = d3.svg.arc().innerRadius(innerRadius).outerRadius(outerRadius)
var chord_svg = d3.svg.chord().radius(innerRadius);
var comp = {
bigger: function(a, b) { return a.value > b.value ? a : b },
smaller: function(a, b) { return a.value < b.value ? a : b }
}
for (key in options) {
self[key] = options[key];
}
self.update = function(data) {
if (!chord.matrix()) {
chord.matrix(data);
self.render();
} else {
var old = {
groups: chord.groups(),
chords: chord.chords()
};
chord.matrix(data);
self.transition(old);
}
};
self.clear = function() {
d3.select(self.container).selectAll('svg').remove();
};
self.transition = function(old) {
svg.selectAll(".arc")
.data(chord.groups)
.transition()
.ease("linear")
.duration(1000)
.attrTween("d", arcTween(arc_svg, old));
svg.selectAll(".chord")
.selectAll("path")
.data(chord.chords)
.transition()
.ease("linear")
.duration(1000)
.style("fill", function(d) { return self.fill(comp[coloring](d.source, d.target).index); })
.attrTween("d", chordTween(chord_svg, old));
};
self.render = function() {
self.clear();
svg = d3.select(self.container)
.append("svg")
.attr("width", w)
.attr("height", h)
.append("g")
.attr("transform", "translate(" + w / 2 + "," + h / 2 + ")");
svg.append("g")
.selectAll("path")
.data(chord.groups)
.enter().append("path")
.attr("class", "arc")
.style("fill", function(d) { return self.fill(d.index); })
.style("stroke", "#ccc")//function(d) { return self.fill(d.index); })
.attr("d", arc_svg);
svg.append("g")
.attr("class", "chord")
.selectAll("path")
.data(chord.chords)
.enter().append("path")
.style("fill", function(d) { return self.fill(comp[coloring](d.source, d.target).index); })
.attr("d", chord_svg)
.style("opacity", 0.8);
self.drawLegend();
};
self.drawLegend = function() {
var legendData = [];
for (var i=0; i<names.length; i++) {
legendData.push({name:names[i],color:color(i)});
}
//TODO: refactor this duplication!!
svg.append("g")
.selectAll("rect")
.data(legendData)
.enter().append("rect")
.attr("class","legend")
.attr("width",25)
.attr("height",25)
.style("fill",function(d) {return d.color;})
.attr("transform", function(d,i) {
return "translate("+ -3*h/4+","+i*30+")"
});
svg.append("g")
.selectAll("text")
.data(legendData)
.enter().append("text")
.attr("x",14)
.attr("dy","0.35em")
.attr("transform", function(d,i) {
var vertPos = i*30 + 13;
return "translate("+ -23*h/32 +","+vertPos+")"
})
.text(function(d){return d.name;})
}
return self;
};
/* Utility functions */
function arcTween(arc_svg, old) {
return function(d,i) {
var i = d3.interpolate(old.groups[i], d);
return function(t) {
return arc_svg(i(t));
}
}
}
function chordTween(chord_svg, old) {
return function(d,i) {
var i = d3.interpolate(old.chords[i], d);
return function(t) {
return chord_svg(i(t));
}
}
}
var counter = 0;
var eventOrder = [];
var jsondata = [];
d3.json(datafile, function(data) {
jsondata = data.events
for (var i=0; i<data.events.length; i++) {
var lenderIndex = null;
for (var j=0; j<names.length; j++) {
if (names[j] === jsondata[i].lender) {
lenderIndex = j;
}
}
for (var j=0; j<names.length; j++) {
for (var k=0; k<data.events[i].borrower.length; k++) {
if (names[j] === jsondata[i].borrower[k]) {
eventOrder.push([lenderIndex,j,jsondata[i].amount,jsondata[i].timeOfDay]);
}
}
}
}
});
function initChord() {
var chord = d3.chart.chord({
container: "#evolution",
fill: color
});
var lender, borrower, amount;
chord.update(lunchData);
setInterval(function() {
if (counter < eventOrder.length-1) {
counter++;
$("#ticker").text(eventOrder[counter][3]);
lender = eventOrder[counter][0];
borrower = eventOrder[counter][1];
amount = eventOrder[counter][2];
lunchData[lender][borrower] += amount;
chord.update(lunchData);
}
}, 1000)
}
var i=0;
initChord();
</script>
</body>
{
"events": [
{
"lender":"Alex",
"borrower":["Liz"],
"timeOfDay":"March 1",
"amount":4
},
{
"lender":"Liz",
"borrower":["Alex"],
"timeOfDay":"March 2",
"amount":5
},
{
"lender":"Alex",
"borrower":["Liz"],
"timeOfDay":"March 3",
"amount":5
},
{
"lender":"Liz",
"borrower":["Alex"],
"timeOfDay":"March 4",
"amount":8
},
{
"lender":"Alex",
"borrower":["Liz"],
"timeOfDay":"March 5",
"amount":3
},
{
"lender":"Liz",
"borrower":["Alex"],
"timeOfDay":"March 6",
"amount":8
},
{
"lender":"Alex",
"borrower":["Liz"],
"timeOfDay":"March 7",
"amount":6
},
{
"lender":"Liz",
"borrower":["Alex"],
"timeOfDay":"March 8",
"amount":5
},
{
"lender":"Alex",
"borrower":["Liz"],
"timeOfDay":"March 9",
"amount":5
},
{
"lender":"Philip",
"borrower":["Lauren"],
"timeOfDay":"March 10",
"amount":15
},
{
"lender":"Lauren",
"borrower":["Philip"],
"timeOfDay":"March 11",
"amount":12
},
{
"lender":"Philip",
"borrower":["Lauren"],
"timeOfDay":"March 12",
"amount":15
},
{
"lender":"Lauren",
"borrower":["Philip"],
"timeOfDay":"March 13",
"amount":12
},
{
"lender":"Philip",
"borrower":["Lauren"],
"timeOfDay":"March 14",
"amount":15
},
{
"lender":"Lauren",
"borrower":["Philip"],
"timeOfDay":"March 15",
"amount":12
},
{
"lender":"Philip",
"borrower":["Lauren"],
"timeOfDay":"March 16",
"amount":15
},
{
"lender":"Lauren",
"borrower":["Philip"],
"timeOfDay":"March 17",
"amount":12
},
{
"lender":"Philip",
"borrower":["Lauren"],
"timeOfDay":"March 18",
"amount":15
},
{
"lender":"Lauren",
"borrower":["Philip"],
"timeOfDay":"March 19",
"amount":12
},
{
"lender":"Lauren",
"borrower":["Philip","Liz","Chris"],
"timeOfDay":"March 20",
"amount":20
},
{
"lender":"Philip",
"borrower":["Lauren","Liz","Chris"],
"timeOfDay":"March 21",
"amount":24
},
{
"lender":"Liz",
"borrower":["Philip","Lauren","Chris"],
"timeOfDay":"March 22",
"amount":23
},
{
"lender":"Chris",
"borrower":["Philip","Liz","Lauren"],
"timeOfDay":"March 23",
"amount":14
},
{
"lender":"Lauren",
"borrower":["Philip","Liz","Chris"],
"timeOfDay":"March 24",
"amount":20
},
{
"lender":"Philip",
"borrower":["Lauren","Liz","Chris"],
"timeOfDay":"March 25",
"amount":24
},
{
"lender":"Liz",
"borrower":["Philip","Lauren","Chris"],
"timeOfDay":"March 26",
"amount":23
},
{
"lender":"Chris",
"borrower":["Philip","Liz","Lauren"],
"timeOfDay":"March 27",
"amount":14
},
{
"lender":"Lauren",
"borrower":["Philip","Liz","Chris"],
"timeOfDay":"March 28",
"amount":20
},
{
"lender":"Philip",
"borrower":["Lauren","Liz","Chris"],
"timeOfDay":"March 29",
"amount":24
},
{
"lender":"Liz",
"borrower":["Philip","Lauren","Chris"],
"timeOfDay":"March 30",
"amount":23
},
{
"lender":"Chris",
"borrower":["Philip","Liz","Lauren"],
"timeOfDay":"March 31",
"amount":14
},
{
"lender":"Lauren",
"borrower":["Alex"],
"timeOfDay":"April 1",
"amount":40
},
{
"lender":"Philip",
"borrower":["Chris"],
"timeOfDay":"April 2",
"amount":16
},
{
"lender":"Alex",
"borrower":["Lauren"],
"timeOfDay":"April 3",
"amount":35
},
{
"lender":"Lauren",
"borrower":["Alex"],
"timeOfDay":"April 4",
"amount":16
},
{
"lender":"Alex",
"borrower":["Lauren"],
"timeOfDay":"April 5",
"amount":35
},
{
"lender":"Lauren",
"borrower":["Alex"],
"timeOfDay":"April 6",
"amount":16
},
{
"lender":"Alex",
"borrower":["Lauren"],
"timeOfDay":"April 7",
"amount":35
},
{
"lender":"Lauren",
"borrower":["Alex"],
"timeOfDay":"April 8",
"amount":16
},
{
"lender":"Alex",
"borrower":["Lauren"],
"timeOfDay":"April 9",
"amount":35
},
{
"lender":"Lauren",
"borrower":["Alex"],
"timeOfDay":"April 10",
"amount":16
},
{
"lender":"Alex",
"borrower":["Lauren"],
"timeOfDay":"April 11",
"amount":19
},
{
"lender":"Lauren",
"borrower":["Alex"],
"timeOfDay":"April 12",
"amount":19
},
{
"lender":"Ryan",
"borrower":["Chris"],
"timeOfDay":"April 13",
"amount":18
},
{
"lender":"Chris",
"borrower":["Ryan"],
"timeOfDay":"April 14",
"amount":18
},
{
"lender":"Ryan",
"borrower":["Chris"],
"timeOfDay":"April 15",
"amount":18
},
{
"lender":"Chris",
"borrower":["Ryan"],
"timeOfDay":"April 16",
"amount":18
},
{
"lender":"Ryan",
"borrower":["Chris"],
"timeOfDay":"April 17",
"amount":18
},
{
"lender":"Chris",
"borrower":["Ryan"],
"timeOfDay":"April 18",
"amount":18
},
{
"lender":"Ryan",
"borrower":["Chris"],
"timeOfDay":"April 19",
"amount":18
},
{
"lender":"Chris",
"borrower":["Ryan"],
"timeOfDay":"April 20",
"amount":18
},
{
"lender":"Ryan",
"borrower":["Philip","Alex"],
"timeOfDay":"April 21",
"amount":37
},
{
"lender":"Lauren",
"borrower":["Liz"],
"timeOfDay":"April 22",
"amount":47
},
{
"lender":"Liz",
"borrower":["Ryan","Alex"],
"timeOfDay":"April 23",
"amount":17
},
{
"lender":"Chris",
"borrower":["Liz"],
"timeOfDay":"April 24",
"amount":27
},
{
"lender":"Chris",
"borrower":["Lauren","Ryan"],
"timeOfDay":"April 25",
"amount":17
},
{
"lender":"Philip",
"borrower":["Lauren"],
"timeOfDay":"April 26",
"amount":20
},
{
"lender":"Lauren",
"borrower":["Philip"],
"timeOfDay":"April 27",
"amount":10
},
{
"lender":"Liz",
"borrower":["Alex","Philip"],
"timeOfDay":"April 28",
"amount":16
},
{
"lender":"Ryan",
"borrower":["Lauren"],
"timeOfDay":"April 29",
"amount":15
},
{
"lender":"Lauren",
"borrower":["Ryan"],
"timeOfDay":"April 30",
"amount":11
},
{
"lender":"Ryan",
"borrower":["Lauren"],
"timeOfDay":"May 1",
"amount":13
},
{
"lender":"Lauren",
"borrower":["Ryan"],
"timeOfDay":"May 2",
"amount":17
},
{
"lender":"Chris",
"borrower":["Alex"],
"timeOfDay":"May 3",
"amount":19
},
{
"lender":"Philip",
"borrower":["Lauren"],
"timeOfDay":"May 4",
"amount":15
},
{
"lender":"Lauren",
"borrower":["Philip"],
"timeOfDay":"May 5",
"amount":12
},
{
"lender":"Ryan",
"borrower":["Philip"],
"timeOfDay":"May 6",
"amount":15
},
{
"lender":"Alex",
"borrower":["Liz"],
"timeOfDay":"May 7",
"amount":19
},
{
"lender":"Liz",
"borrower":["Alex"],
"timeOfDay":"May 8",
"amount":35
},
{
"lender":"Chris",
"borrower":["Liz"],
"timeOfDay":"May 9",
"amount":19
},
{
"lender":"Lauren",
"borrower":["Alex"],
"timeOfDay":"May 10",
"amount":3
},
{
"lender":"Philip",
"borrower":["Alex","Liz"],
"timeOfDay":"May 11",
"amount":10
},
{
"lender":"Philip",
"borrower":["Ryan"],
"timeOfDay":"May 12",
"amount":20
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment