{
let top5Countries = ["NL", "GB", "US", "NO", "DK"];
let months = {};
let cetaceansByMonth = [];
for (let c = 0; c < top5Countries.length; c++) {
for (let i = 0; i < cetacea.length; i++) {
if (cetacea[i].countryCode == top5Countries[c]) {
let sightingMonth = cetacea[i].countryCode + cetacea[i].month;
if (sightingMonth in months) {
months[sightingMonth]++;
} else {
months[sightingMonth] = 1;
}
}
}
}
for (let property in months) {
cetaceansByMonth.push({
name: property,
count: months[property]
});
}
//svg variablesj
let width = 800;
let height = 400;
let margin = 25;
//create SVG artboard
let svg = d3
.create("svg")
.attr("viewBox", [0, 0, width, height])
.attr("width", width)
.attr("height", height)
.attr("fill", "#e5d8bd");
//create SVG background
let bg = svg
.append("rect")
.attr('x', 0)
.attr('y', 0)
.attr("width", width)
.attr("height", height);
//accessor function to find min and max counts
let monthMinMax = d3.extent(cetaceansByMonth, d => d.count);
//scales for counts to parameters
let monthParameterScale = d3
.scaleLinear()
.domain(monthMinMax)
.range([0, 1]);
// calculate the gap between each vertical line
let verticalGap = (height - margin * 2) / 12;
// scales for counts to pixels
let monthSizeScale = d3
.scaleLinear()
.domain(monthMinMax)
.range([0, verticalGap]);
// calculate the gap between each horizontal line
let horizontalGap = (width - margin * 2) / top5Countries.length;
// loop throught all items in dataset
for (let i = 0; i < cetaceansByMonth.length; i++) {
for (let c = 0; c < top5Countries.length; c++) {
if (cetaceansByMonth[i]["name"].slice(0, 2) == top5Countries[c]) {
// for converting data to pixels
let circleRadius = monthSizeScale(
parseFloat(cetaceansByMonth[i].count)
);
// for converting data to parameter between 0 and 1
let barParameter = monthParameterScale(
parseFloat(cetaceansByMonth[i].count)
);
let monthNumber = cetaceansByMonth[i]["name"].slice(2);
// draw circle for each month
svg
.append("circle")
.attr("cx", (c + 1) * horizontalGap)
.attr("cy", monthNumber * verticalGap)
.attr("r", circleRadius)
.attr("fill", d3.interpolateViridis(barParameter))
.attr("opacity", .5);
// label country name
svg
.append("text")
.attr("x", (c + 1) * horizontalGap)
.attr("y", height - margin / 2)
.text(cetaceansByMonth[i]["name"].slice(0, 2))
.attr("fill", "black")
.attr("text-anchor", "middle")
.attr("fill", "#616161")
.attr("font-family", "Arial, Helvetica, sans-serif");
let monthName = [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec'
];
// label month name
svg
.append("text")
.attr("x", margin)
.attr("y", monthNumber * verticalGap)
.text(monthName[monthNumber - 1])
.attr("fill", "black")
.attr("transform", "translate(0 5)")
.attr("fill", "#616161")
.attr("font-size", "0.75em")
.attr("font-family", "Arial, Helvetica, sans-serif");
}
}
}
//show visualization in Observable
return svg.node();
}