diff --git a/index.html b/index.html index 2b804c7..143d13d 100644 --- a/index.html +++ b/index.html @@ -29,6 +29,9 @@ body { + + + @@ -201,6 +204,9 @@ body {
Sort By Goals Scored
+
+
Sort By Country Population
+
@@ -208,200 +214,6 @@ body {
- - -
Lessons learned
scaleOrdinal vs scaleLinear (only 2 colors!) vs interpolateCool vs d3.schemeColor20c
diff --git a/js/diagram.js b/js/diagram.js new file mode 100644 index 0000000..94c8472 --- /dev/null +++ b/js/diagram.js @@ -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) +// }; diff --git a/js/main.js b/js/main.js new file mode 100644 index 0000000..b33e913 --- /dev/null +++ b/js/main.js @@ -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); diff --git a/js/matrices.js b/js/matrices.js new file mode 100644 index 0000000..5ac920f --- /dev/null +++ b/js/matrices.js @@ -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; + }, +}; diff --git a/js/ui.js b/js/ui.js new file mode 100644 index 0000000..88fb315 --- /dev/null +++ b/js/ui.js @@ -0,0 +1,2 @@ +const UI = { +};