visualizationOne = {
const radius = Math.min(width, height) / 3.5;
const colorScale = d3.scaleOrdinal()
.domain(["Sony", "Nintendo", "Microsoft", "Sega", "PC"])
.range(["green", "red", "blue", "orange", "grey"]);
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
.style("font", "12px sans-serif");
const pie = d3.pie() // D3 function that computes pie layout
.value(d => d.count) // Each slice size is based on company game count
.sort(null); // Keep original order (don’t sort slices)
const arc = d3.arc() // Generator to build each arc shape
.outerRadius(radius) // Full size of slice (no donut)
.innerRadius(0); // 0 for full pie (not donut)
// STEP FOUR: Tooltip logic (shown on hover)
const tooltip = d3.select("body").append("div") // Create floating tooltip div
.attr("class", "tooltip") // Assign CSS class
.style("position", "absolute") // Float it relative to page
.style("pointer-events", "none") // Disable interactions
.style("padding", "8px") // Style: padding
.style("background", "white") // Background color
.style("border", "1px solid #ccc") // Light border
.style("border-radius", "4px") // Rounded corners
.style("box-shadow", "0 2px 6px rgba(0,0,0,0.1)") // Subtle drop shadow
.style("opacity", 0); // Start invisible
// STEP FIVE: Function to draw one pie chart
// Accepts the data, a horizontal position, and a label (i.e. time range)
function drawPie(data, cx, label) {
const g = svg.append("g") // Create new group for this pie
.attr("transform", `translate(${cx},${height / 2})`); // Center pie at (cx, middle of SVG)
const pieData = pie(data); // Run pie layout on data
const total = d3.sum(data, d => d.count); // Total games, used to calculate percentages
// STEP SIX: Draw each pie slice
g.selectAll("path") // For each slice (path element)
.data(pieData) // Bind pie-layout data
.enter()
.append("path") // Create SVG path for slice
.attr("d", arc) // Generate arc shape
.attr("fill", d => colorScale(d.data.company)) // Color based on company
// STEP SEVEN: Hover functionality for the mouseover!
.on("mouseover", (event, d) => { // Create and define the tooltip event
tooltip
.html(`
<strong>${d.data.company}</strong><br>
${d.data.tooltip.replace(/\n/g, "<br>")}`) // Set tooltip content: bold company name and multiline tooltip info
.style("left", (event.pageX + 10) + "px") // Position tooltip horizontally beside mouse
.style("top", (event.pageY + 10) + "px") // vertically beside
.style("opacity", 1); // Pop into view!
})
.on("mouseout", () => { // ... Back to transparent!
tooltip.style("opacity", 0);
});
// STEP EIGHT: Percent labels on the slices!
g.selectAll("text.label") // Select text elements with class "label"
.data(pieData) // Bind pie chart data (angle-based)
.enter() // enter() = For each data item, create a new text element
.append("text")
.attr("class", "label") // Add CSS class for any future styling
.attr("transform", d => `translate(${arc.centroid(d)})`)
// Use arc.centroid(d) to get [x, y] at the center of the slice, and move the label there
.attr("text-anchor", "middle") // Center-align the text horizontally
.attr("dy", "0.35em") // Vertical offset so label sits visually centered
.style("fill", "white") // White text for contrast on colored slices
.style("font-weight", "bold") // Make labels visually strong
.text(d => `${((d.data.count / total) * 100).toFixed(1)}%`); // Computers the percent, to a single decimal place, for slices
// STEP NINE: Pie labels!
g.append("text") // Append a new <text> element to the pie group
.attr("y", radius + 20) // Position below the pie chart (20px below radius)
.attr("text-anchor", "middle") // Centered horizontally with respect to pie
.attr("font-weight", "bold") // Bold for visibility
.text(label); // Set the label (We got this passed )
}
// STEP TEN: Draw two pie charts for the two eras
// This shifts the positioning, artistic choices
drawPie(processedData.byPeriod.before2010, width * 0.22, "1996–2009")
drawPie(processedData.byPeriod.after2009, width * 0.58, "2010–2023");
// STEP ELEVEN: Build the legend
const legend = svg.append("g")
.attr("transform", `translate(${width - margin.right}, ${margin.top})`);
// Create a group <g> element for the legend, positioned in top-right corner
const companies = ["Sony", "Nintendo", "Microsoft", "Sega", "PC"];
// Manually define the set of companies expected in the pie charts
companies.forEach((company, i) => {
const legendRow = legend.append("g")
.attr("transform", `translate(0, ${i * 20})`);
// Create a horizontal legend row for each company, stacking vertically (20px apart)
legendRow.append("rect")
.attr("width", 12)
.attr("height", 12)
.attr("fill", colorScale(company)); // Legend box, for the companies
legendRow.append("text")
.attr("x", -8) // Alighment for the square
.attr("y", 10)
.attr("text-anchor", "end") // Right-align the text
.text(company); // Display the company name
});
return svg.node();
}