scatterPlot = {
const width = 800;
const height = 600;
const margin = {top: 30, right: 30, bottom: 60, left: 60};
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height + 60])
.attr("style", "max-width: 100%, height: auto, font: 10px sans-serif");
const parseDate = d3.timeParse("%d-%b-%y");
const dateData = data
.filter(d => d["Date"] && d.Metascore)
.map(d => {
const parsedDate = parseDate(d["Date"]);
const metascore = parseFloat(d.Metascore);
const platform = d.Platform;
const manufacturer = platformToManufacturer[platform];
return{
date: parsedDate,
metascore: metascore,
platform: platform,
manufacturer: manufacturer
};
})
.filter(d => !isNaN(d.date) && !isNaN(d.metascore) && d.manufacturer);
const dateExtent = d3.extent(dateData, d => d.date)
const timePadding = (dateExtent[1] - dateExtent[0]) * 0.05;
const x = d3.scaleTime()
.domain([new Date(dateExtent[0].getTime() - timePadding), new Date(dateExtent[1].getTime() + timePadding)])
.range([margin.left, width - margin.right]);
const y = d3.scaleLinear()
.domain([90, d3.max(dateData, d => d.metascore)])
.nice()
.range([height - margin.bottom, margin.top]);
svg.append("g")
.attr("stroke", "black")
.selectAll("circle")
.data(dateData)
.join("circle")
.attr("cx", d => x(d.date))
.attr("cy", d => y(d.metascore))
.attr("r", 5)
.attr("opacity", 0.85)
.attr("fill", d => manufacturerColor(d.manufacturer))
.append("title").text(d => `${d.platform} (${d.manufacturer}): ${d.metascore}`);
svg.append("g")
.attr("transform", `translate(0, ${height - margin.bottom})`)
.call(d3.axisBottom(x));
svg.append("g")
.attr("transform", `translate(${margin.left}, 0)`)
.call(d3.axisLeft(y));
svg.append("text")
.attr("x", width / 2)
.attr("y", margin.top / 2)
.attr("text-anchor", "middle")
.attr("font-size", "16px")
.attr("font-weight", "bold")
.text("Metascore Over Time (Colored by Manufacturer)");
const legendGroup = svg.append("g")
.attr("transform", `translate(${margin.left}, ${height - margin.bottom + 40})`);
[...new Set(
platformCounts
.map(d => d.manufacturer)
.filter(m => m !== undefined && m !== "Other")
)].forEach((manufacturer, i) => {
const group = legendGroup.append("g").attr("transform", `translate(${i * 120}, 0)`);
group.append("rect").attr("width", 20).attr("height", 20).attr("fill", manufacturerColor(manufacturer));
group.append("text")
.attr("x", 25)
.attr("y", 15)
.text(manufacturer)
.attr("font-size", "16px")
.attr("alignment-baseline", "middle");
});
return svg.node();
}