// svg.call(d3.zoom()
// .scaleExtent([1, 8]) // min/max zoom level
// .on("zoom", (event) => {
// g.attr("transform", event.transform);
// })
// );
// return svg.node();
// }
mapChart = {
const width = 940, height = 650;
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.style("border", "1px solid #ccc");
const g = svg.append("g");
const projection = d3.geoMercator().scale(150).translate([width / 2, height / 1.5]);
const path = d3.geoPath(projection);
const data = movieCountsByYear[selectedYear] || {};
const totalCount = d3.sum(Object.values(data), d => d.count || 0);
const maxCount = d3.max(Object.values(data), d => d.count || 0);
let maxValue;
let color;
if (mapMetric === "Movie Count") {
maxValue = d3.max(Object.values(data), d => d.count || 0);
color = d3.scaleSequential(d3.interpolateOranges).domain([0, maxValue || 1]);
} else {
maxValue = 10; // IMDb ratings cap at 10
color = d3.scaleSequential(d3.interpolateBlues).domain([0, maxValue]);
}
g.selectAll("path")
.data(customGeoJSON.features)
.join("path")
.attr("d", path)
.attr("fill", d => {
const record = data[d.properties.name];
if (!record) return "#eee";
if (mapMetric === "Movie Count") return color(record.count);
if (record.ratingCount > 0) {
const avgRating = record.ratingSum / record.ratingCount;
return color(avgRating);
}
return "#eee";
})
.attr("stroke", "#333")
.append("title")
.text(d => {
const name = d.properties.name;
const record = data[name];
if (!record) return `${name}\nNo data`;
const { count, revenue, ratingSum, ratingCount } = record;
const percent = totalCount > 0 ? ((count / totalCount) * 100).toFixed(2) : "0.00";
const revenueDisplay = revenue > 0 ? `$${revenue.toLocaleString()}` : "Unknown";
const avgRating = ratingCount > 0 ? (ratingSum / ratingCount).toFixed(2) : "N/A";
return `${name}
Movies: ${count} (${percent}%)
Revenue: ${revenueDisplay}
Avg IMDb Rating: ${avgRating}`;
});
svg.call(d3.zoom()
.scaleExtent([1, 8])
.on("zoom", (event) => {
g.attr("transform", event.transform);
})
);
return svg.node();
}