Published
Edited
May 20, 2020
4 stars
Insert cell
Insert cell
Insert cell
Insert cell
function make_b1g_coord_diagram(w) {
let container = d3.create('div').style('width', `${w * width}px`);
let svg = container
.append("svg")
.style('background-color', 'white')
.attr("viewBox", [-0.5 * width, -0.5 * height, 1 * width, 1 * height])
.attr("font-size", 10)
.attr("font-family", "sans-serif");

let chords = chord(M.toArray());
let arcs = svg
.append("g")
.selectAll("g")
.data(chords.groups)
.join("g");
arcs
.append("path")
.attr("fill", d => team_colors(d.index)[0])
.attr("stroke", d => d3.rgb(team_colors(d.index)[0]).darker())
.attr("d", arc1);
arcs
.append("path")
.attr("fill", d => team_colors(d.index)[1])
.attr("stroke", d => d3.rgb(team_colors(d.index)[1]).darker())
.attr("d", arc2);

let ribbons = svg
.append("g")
.attr('opacity', 0.7)
.selectAll("path")
.data(chords)
.join("path")
.attr("d", ribbon)
.attr('class', function(d) {
let team1 = teams[d.source.index].name.replace(/ /g, '');
let team2 = teams[d.target.index].name.replace(/ /g, '');
return `chord ${team1} ${team2}`;
})
.attr("fill", d => team_colors(d.source.index)[0])
.attr("stroke", d => d3.rgb(team_colors(d.source.index)[0]).darker())
.on('mouseenter', function() {
svg.selectAll('.chord').attr('opacity', 0.1);
d3.select(this).attr('opacity', 1);
})
.on('mouseleave', function() {
svg.selectAll('.chord').attr('opacity', 1);
})
.attr('title', function(d) {
let score1 = M.toArray()[d.source.index][d.target.index];
let score2 = M.toArray()[d.target.index][d.source.index];
let team1 = teams[d.source.index].name;
let team2 = teams[d.target.index].name;
return `${team1} ${score1} \n ${team2} ${score2}`;
});
ribbons.nodes().forEach(e =>
tippy(e, {
delay: [200, 100],
duration: [100, 50],
followCursor: true
})
);

let logos = arcs
.append("g")
.selectAll("image")
.data(chords.groups)
.join("image")
.attr("x", function(d) {
let theta = (d.startAngle + d.endAngle) / 2;
return 0.97 * scale(Math.cos(theta - Math.PI / 2));
})
.attr("y", function(d) {
let theta = (d.startAngle + d.endAngle) / 2;
return 0.97 * scale(Math.sin(theta - Math.PI / 2));
})
.attr('width', function(d) {
if (teams[d.index].logo_size) {
return teams[d.index].logo_size;
} else {
return 30;
}
})
.attr('height', function(d) {
if (teams[d.index].logo_size) {
return teams[d.index].logo_size;
} else {
return 30;
}
})
.attr('transform', function(d) {
if (teams[d.index].logo_size) {
let shift = -teams[d.index].logo_size / 2;
return `translate(${shift}, ${shift})`;
} else {
return 'translate(-15,-15)';
}
})
.attr("xlink:href", d => teams[d.index].logo_url)
.on('mouseenter', function(d) {
let this_class = '.' + teams[d.index].name.replace(/ /g, '');
svg.selectAll('.chord').attr('opacity', 0.1);
svg.selectAll(this_class).attr('opacity', 1);
})
.on('mouseleave', function() {
svg.selectAll('.chord').attr('opacity', 1);
})
.attr('title', function(d) {
let name = teams[d.index].name;
let scored = d3.sum(M.toArray()[d.index]);
let scored_against = d3.sum(M.toArray().map(r => r[d.index]));
return `${name} scored ${scored} points against ${scored_against} scored by their opponents.`;
});

logos.nodes().forEach(e =>
tippy(e, {
delay: [200, 100],
duration: [100, 50]
})
);

return container.node();
}
Insert cell
scale = d3
.scaleLinear()
.domain([-1, 1])
.range([-height / 2, height / 2])
Insert cell
chords = chord(M.toArray())
Insert cell
chord = d3
.chord()
.padAngle(0.05)
.sortSubgroups(d3.descending)
Insert cell
arc2 = d3
.arc()
.innerRadius(r)
.outerRadius(r_out)
Insert cell
arc1 = d3
.arc()
.innerRadius(r_in)
.outerRadius(r)
Insert cell
ribbon = d3.ribbon().radius(r_in)
Insert cell
team_colors = d3
.scaleOrdinal()
.domain(d3.range(14))
.range(teams.map(d => d.colors))
Insert cell
s = 20
Insert cell
r_out = r + s
Insert cell
r_in = r - s
Insert cell
r = Math.min(width, height) * 0.5 - s
Insert cell
height = 0.8 * width
Insert cell
// Add some styling information for each team
tc = teams.forEach(function(team) {
if (team.name == 'Illinois') {
team.colors = ['#E84A27', '#13294B'];
team.logo_url =
'https://upload.wikimedia.org/wikipedia/commons/9/91/Illinois_Fighting_Illini_logo.svg';
} else if (team.name == 'Indiana') {
team.colors = ['#990000', '#EDEBEB'];
team.logo_url =
'https://upload.wikimedia.org/wikipedia/commons/4/47/Indiana_Hoosiers_logo.svg';
} else if (team.name == 'Iowa') {
team.colors = ['#000000', '#FCD116'];
team.logo_url =
'https://upload.wikimedia.org/wikipedia/en/7/7b/Iowa_Hawkeyes_logo.svg';
} else if (team.name == 'Maryland') {
team.colors = ['#CF102D', '#FFFFFF'];
team.logo_url =
'https://upload.wikimedia.org/wikipedia/commons/a/a6/Maryland_Terrapins_logo.svg';
} else if (team.name == 'Michigan') {
team.colors = ['#FFCB05', '#00274C'];
team.logo_url =
'https://upload.wikimedia.org/wikipedia/commons/f/fb/Michigan_Wolverines_logo.svg';
} else if (team.name == 'Michigan St') {
team.colors = ['#18453B', '#FFFFFF'];
team.logo_url =
'https://upload.wikimedia.org/wikipedia/en/a/a7/Michigan_State_Athletics_logo.svg';
} else if (team.name == 'Minnesota') {
team.colors = ['#FBB93C', '#862334'];
team.logo_url =
'https://upload.wikimedia.org/wikipedia/commons/f/f9/Minnesota_Golden_Gophers_logo.svg';
} else if (team.name == 'Nebraska') {
team.colors = ['#E41C38', '#FDF2D9'];
team.logo_url =
'https://upload.wikimedia.org/wikipedia/commons/e/e5/Nebraska_Cornhuskers_logo.svg';
} else if (team.name == 'Northwestern') {
team.colors = ['#4E2A84', '#FFFFFF'];
team.logo_url =
'https://upload.wikimedia.org/wikipedia/commons/7/7c/Northwestern_Wildcats_logo.svg';
} else if (team.name == 'Ohio St') {
team.colors = ['#B0B7BC', '#CE0F3D'];
team.logo_url =
'https://upload.wikimedia.org/wikipedia/commons/c/c1/Ohio_State_Buckeyes_logo.svg';
} else if (team.name == 'Penn St') {
team.colors = ['#002D62', '#FFFFFF'];
team.logo_url =
'https://upload.wikimedia.org/wikipedia/en/3/3a/Penn_State_Nittany_Lions_logo.svg';
} else if (team.name == 'Purdue') {
team.colors = ['#CEB888', '#000000'];
team.logo_url =
'https://upload.wikimedia.org/wikipedia/commons/3/35/Purdue_Boilermakers_logo.svg';
} else if (team.name == 'Rutgers') {
team.logo_size = 25;
team.colors = ['#CC0033', '#000000'];
team.logo_url =
'https://upload.wikimedia.org/wikipedia/commons/b/b6/Rutgers_Scarlet_Knights_logo.svg';
} else if (team.name == 'Wisconsin') {
team.colors = ['#C4012F', '#FFFFFF'];
team.logo_url =
'https://upload.wikimedia.org/wikipedia/commons/e/e5/Wisconsin_Badgers_logo.svg';
}
})
Insert cell
import { M, teams } from '@mcmcclur/b1g-football-2019'
Insert cell
tippy = require("https://unpkg.com/tippy.js@2.5.4/dist/tippy.all.min.js")
Insert cell
d3 = require("d3@5")
Insert cell
small_coord_diagram = make_b1g_coord_diagram(0.5)
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more