Public
Edited
Oct 4, 2023
Insert cell
md
`# Animated Map of IOWA COVID-19 Cases (Draft)`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
map = {
// Create SVG
var svg = d3.select(DOM.svg(width, height));
var selectedCounty = null; // Variable to store the clicked county's FIPS code

// Create map
var countyMap = svg.append("g")
.selectAll("path")
.data(counties.features)
.enter()
.append("path")
.attr("d", path)
.attr("fill", "#cccc")
.attr("stroke", "white")
.attr("stroke-width", 0.1)
.on("mouseover", handleMouseOver)
.on("mouseout", handleMouseOut)
.on("click", handleClick); // New line: Add click event


// Draw the state boundaries (could do this in a cleaner way with topoJSON)
svg.append("g")
.selectAll("path")
.data(states.features)
.enter()
.append("path")
.attr("d", path)
.attr("stroke", "white")
.attr("stroke-width", 1)
.attr("fill", "none");

// Add legend
var legendGroup = svg.append("g")
.attr("transform", "translate(20,50)")
.attr("width", 100)
.attr("height", 300);
//////
var legendItems = legendGroup
.selectAll("g")
.data(color.range()) // Use the color range to determine legend items
.enter()
.append("g")
.attr("transform", function(d, i) {
return "translate(0, " + (i * 25) + ")"; // Adjust the vertical spacing
});
legendItems
.append("rect")
.attr("width", 20) // Adjust the width of the legend color box
.attr("height", 20) // Adjust the height of the legend color box
.attr("fill", function(d) {
return d; // Use the color for each legend item
});

///////
var legendElement = legendGroup.append(() => legend({
color,
title: var1_select,
ticks: bins,
tickFormat: ",.2f",
width: 400,
height: 60
}));

// Update the fill based on date scrubber
function update(date) {
countyMap.attr("fill", function(d) {
var map_var = data.get(d.properties["COUNTY_FIPS"] + " " + dateToString(date));

if (map_var) {
var fcolor = color(map_var);
} else {
var fcolor = "#cccc";
}

return fcolor;
});
}

// Function to handle legend hover
function handleLegendHover(d, i) {
// Get the corresponding bin range from the color scale
var range = color.range();
var binIndex = i;
var binColor = range[binIndex];

// Highlight the corresponding selection on the map
countyMap.attr("stroke", function(d) {
var map_var = data.get(d.properties["COUNTY_FIPS"] + " " + dateToString(date));
if (map_var) {
var fcolor = (color(map_var) === binColor) ? "green" : "white";
} else {
var fcolor = "white";
}

return fcolor;
})
.attr("stroke-width", function(d) {
var map_var = data.get(d.properties["COUNTY_FIPS"] + " " + dateToString(date));
if (map_var) {
var fcolor = (color(map_var) === binColor) ? 5 : 0.1;
} else {
var fcolor = 0.1;
}

return fcolor;
});
// highlight the legend color box
d3.select(this)
.attr("stroke", "red")
.attr("stroke-width", 2);
}

// Function to handle legend mouseout
function handleLegendMouseOut() {
// Restore the original stroke colors and widths on the map
countyMap.attr("stroke", "white")
.attr("stroke-width", 0.1);
// revert the legend color box stroke color and width
d3.select(this)
.attr("stroke", "none");
}

// Function to handle mouseover event
function handleMouseOver(d) {
// Example: Change fill color on hover
d3.select(this)
.attr("fill", "red");
// Show the tooltip
var tooltip = d3.select("body")
.append("div")
.attr("class", "tooltip")
.style("position", "absolute")
.style("opacity", 0)
.html("County: " + d.properties["NAME"] + "<br/>Data: " + d.var1_select)
.style("left", d3.event.pageX + "px")
.style("top", d3.event.pageY + "px");
tooltip.transition()
.duration(300)
.style("opacity", 0.9);
}

// Function to handle click event
function handleClick(d) {
d3.select(this)
.attr("stroke", "red") // Highlight clicked polygon
.attr("stroke-width", 2);
selectedCounty = d.properties["COUNTY_FIPS"]; // Store clicked county's FIPS code
}

// Function to handle mouseout event
function handleMouseOut(d) {
// Only revert color if it's not the selected county
if (selectedCounty !== d.properties["COUNTY_FIPS"]) {
d3.select(this)
.attr("fill", function(d) {
var map_var = data.get(d.properties["COUNTY_FIPS"] + " " + dateToString(date));
if (map_var) {
var fcolor = color(map_var);
} else {
var fcolor = "#cccc";
}
return fcolor;
})
.attr("stroke", "white") // Revert stroke color
.attr("stroke-width", 0.1); // Revert stroke width
}

// Remove the tooltip
d3.select(".tooltip").remove();
}

// Function to handle legend click
function handleLegendClick(d, i) {
var binInfoBox = legendGroup.select(".bin-info-box");
if (binInfoBox.empty()) {
binInfoBox = legendGroup
.append("text")
.attr("class", "bin-info-box")
.attr("x", 500)
.attr("y", 30)
.style("font-size", "12px")
.style("fill", "black")
.text("You are viewing the bin information of this legend");
} else {
binInfoBox.remove();
}
}

// Attach event listeners to the legend elements
legendElement.selectAll("rect")
.on("mouseover", handleLegendHover)
.on("mouseout", handleLegendMouseOut)
.on("click", handleLegendClick);

return Object.assign(svg.node(), { update });
}

Insert cell
Insert cell
dates = (async function() {
const response = await FileAttachment("covid_demographics_data.csv").text();
const rows = d3.csvParse(response);
const uniqueDates = [...new Set(rows.map(d => d.date))];
return uniqueDates;
})();
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
states = JSON.parse(JSON.stringify(rawStates))
Insert cell
states.features = stateFeatures
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// Create a color scale with 4 colors
color_draft = d3.scaleQuantize()
.domain([0, 1]) // Update the domain based on your data
.range(["#color1", "#color2", "#color3", "#color4"]);

Insert cell
Insert cell
iowaProjection = d3.geoAlbers()
.center([0, 41.5])
.rotate([93, 0])
.parallels([29.5, 45.5])
.scale(6000)
.translate([width / 2, height / 2]);
Insert cell
usStatesData = await d3.json('https://d3js.org/us-10m.v1.json');
Insert cell
path = d3.geoPath().projection(iowaProjection);
Insert cell
projection = d3.geoAlbersUsa()
.translate( [width/2, height/2] );
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function dateToString(date) {
var year = date.getFullYear();
var month = ("0" + (date.getMonth() + 1)).slice(-2);
var day = ("0" + date.getDate()).slice(-2);
return `${year}-${month}-${day}`;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more