parent
0819057c79
commit
aefdade7ea
5 changed files with 170 additions and 194 deletions
@ -0,0 +1,104 @@ |
||||
const Diagram = { |
||||
build: (eventIndex, data, metaMatrix, chordMatrix) => { |
||||
const svg = d3.select("svg"), |
||||
width = +svg.attr("width"), |
||||
height = +svg.attr("height"), |
||||
outerArcThickness = 5, |
||||
outerRadius = Math.min(width, height) * 0.5 - 100, |
||||
innerRadius = outerRadius - outerArcThickness; |
||||
|
||||
const chord = d3.chord() |
||||
.padAngle(0.05); |
||||
|
||||
const arc = d3.arc() |
||||
.innerRadius(innerRadius) |
||||
.outerRadius(outerRadius); |
||||
|
||||
const ribbon = d3.ribbon() |
||||
.radius(innerRadius); |
||||
|
||||
// const color = d3.scaleOrdinal(d3.schemeCategory20);
|
||||
// const color = d3.scaleOrdinal(d3.schemeCategory10);
|
||||
// const color = d3.scaleOrdinal(d3.interpolateCool);
|
||||
// const color = d3.scaleSequential(d3.interpolateRainbow);
|
||||
|
||||
const color = d3.scaleLinear().domain([0,10]).range(["red", "blue"]).interpolate(d3.interpolateRgb) |
||||
|
||||
// const colors = ["#f1eef6","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#91003f"];
|
||||
// const colors = ["#ffffcc","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#0c2c84"];
|
||||
// const colors = ["#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"];
|
||||
// const colors = ["#1B9E77", "#D95F02", "#7570B3", "#E7298A", "#66A61E", "#E6AB02", "#A6761D", "#666666"];
|
||||
// const color = i => colors[i % colors.length];
|
||||
|
||||
const g = svg.append("g") |
||||
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")") |
||||
.datum(chord(chordMatrix)); |
||||
|
||||
const group = g.append("g") |
||||
.attr("class", "groups") |
||||
.selectAll("g") |
||||
.data(function(chords) { return chords.groups; }) |
||||
.enter().append("g"); |
||||
|
||||
group.append("path") |
||||
.style("fill", function(d) { return color(d.index); }) |
||||
.style("stroke", function(d) { return d3.rgb(color(d.index)).darker(); }) |
||||
.attr("d", arc); |
||||
|
||||
g.append("g") |
||||
.attr("class", "ribbons") |
||||
.selectAll("path") |
||||
.data(function(chords) { return chords; }) |
||||
.enter().append("path") |
||||
.attr("d", ribbon) |
||||
.style("fill", function(d) { return color(d.target.index); }) |
||||
.style("stroke", function(d) { return d3.rgb(color(d.target.index)).darker(); }) |
||||
.attr("class", "ribbon") |
||||
// .append("title")
|
||||
// .text(function(d) {
|
||||
// const meta1 = metaMatrix[d.target.index][d.source.index];
|
||||
// const meta2 = metaMatrix[d.source.index][d.target.index];
|
||||
//
|
||||
// const g = meta1.game;
|
||||
//
|
||||
// const t1 = lookup.teams[g.t1];
|
||||
// const t2 = lookup.teams[g.t2];
|
||||
//
|
||||
// const e1 = g.s1e ? `(+${g.s1e} in extended time)` : '';
|
||||
// const e2 = g.s2e ? `(+${g.s2e} in extended time)` : '';
|
||||
//
|
||||
// const p1 = g.s1p ? `(+${g.s1p} in penalties)` : '';
|
||||
// const p2 = g.s2p ? `(+${g.s2p} in penalties)` : '';
|
||||
//
|
||||
// return `${t1}: ${g.s1} ${e1} ${p1}\n${t2}: ${g.s2} ${e2} ${p2}`;
|
||||
// });
|
||||
|
||||
group.append("text") |
||||
.each(function(d) { d.angle = (d.startAngle + d.endAngle) / 2; }) |
||||
.attr("dy", ".35em") |
||||
.attr("transform", function(d) { |
||||
return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")" |
||||
+ "translate(" + (innerRadius + 26) + ")" |
||||
+ (d.angle > Math.PI ? "rotate(180)" : ""); |
||||
}) |
||||
.style("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; }) |
||||
.text(function(d) { |
||||
// SORT BY GOALS SCORED
|
||||
// SORT BY ALPHABETICAL
|
||||
// SORT BY COUNTRY SIZE
|
||||
// SORT BY COUNTRY POPULATION
|
||||
// COLOR BY CONTINENT
|
||||
// STRANGE EXTENDED TIME CHILE-BRAZIL - FIX BY HAND? IS BECAUE se1 IS SCORE __GOING INTO__ EXTENDED TIME
|
||||
// console.info(metaMatrix[d.index])
|
||||
const t = data.tourneys[eventIndex].teams[d.index]; |
||||
const c = data.countries[data.teams[t]]; |
||||
return data.countries[data.teams[t]].n; |
||||
}); |
||||
}, |
||||
}; |
||||
|
||||
// const main = (data) => {
|
||||
// const lookup = buildLookup(endpoints, data);
|
||||
// const chordMatrix = buildChordMatrix(lookup.games, lookup.reducedTeams)
|
||||
// const metaMatrix = buildMetaMatrix(lookup.games, lookup.reducedTeams)
|
||||
// };
|
@ -0,0 +1,19 @@ |
||||
const fetch = (url) => new Promise((resolve, reject) => { |
||||
const listener = ({ srcElement: req }) => { |
||||
req.status === 200 ? resolve(req.responseText) : reject("busted"); |
||||
}; |
||||
|
||||
const req = new XMLHttpRequest(); |
||||
req.addEventListener('load', listener); |
||||
req.open('GET', url); |
||||
req.send(); |
||||
}); |
||||
|
||||
const main = function(strData) { |
||||
const json = JSON.parse(strData); |
||||
const metaMatrix = Matrices.buildMetaMatrix(json, "1930"); |
||||
const chordMatrix = Matrices.buildChordMatrix(json, "1930"); |
||||
Diagram.build("1930", json, metaMatrix, chordMatrix); |
||||
} |
||||
|
||||
fetch('worldcup.json').then(main); |
@ -0,0 +1,39 @@ |
||||
const Matrices = { |
||||
// A x A array of nulls; null-null relationships are omitted in chord diagram.
|
||||
createEmptyMatrix: (len) => { |
||||
const empty = Array.apply(null, Array(len)); |
||||
return empty.map(() => empty.map(() => null)); |
||||
}, |
||||
|
||||
// Identical structure of chord matrix but with { game, team }.
|
||||
buildMetaMatrix: (json, eventKey) => { |
||||
const teams = json.tourneys[eventKey].teams; |
||||
const matrix = Matrices.createEmptyMatrix(teams.length); |
||||
|
||||
json.tourneys[eventKey].games.forEach(g => { |
||||
const i1 = teams.indexOf(g.t1); |
||||
const i2 = teams.indexOf(g.t2); |
||||
|
||||
matrix[i1][i2] = { game: g, team: g.t1 }; |
||||
matrix[i2][i1] = { game: g, team: g.t2 }; |
||||
}, []); |
||||
|
||||
return matrix; |
||||
}, |
||||
|
||||
// Scalar data points (sum of goals scored).
|
||||
buildChordMatrix: (json, eventKey) => { |
||||
const teams = json.tourneys[eventKey].teams; |
||||
const matrix = Matrices.createEmptyMatrix(teams.length); |
||||
|
||||
json.tourneys[eventKey].games.forEach(g => { |
||||
const i1 = teams.indexOf(g.t1); |
||||
const i2 = teams.indexOf(g.t2); |
||||
|
||||
matrix[i1][i2] = g.s1 + g.se1 + g.sp1; |
||||
matrix[i2][i1] = g.s2 + g.se2 + g.sp2; |
||||
}, []); |
||||
|
||||
return matrix; |
||||
}, |
||||
}; |
Loading…
Reference in new issue