Public
Edited
Nov 3, 2022
Insert cell
Insert cell
Insert cell
usStates.features[0].geometry.coordinates[0]
Insert cell
Insert cell
Insert cell
Insert cell
usCities = FileAttachment("us-cities.csv").csv({ typed: true })
Insert cell
{
const width = 512;
const height = 512;

const svg = d3.create("svg").attr("width", width).attr("height", height);

// Try changing the projection of the map.
// You can see a full list of projections here:
// https://github.com/d3/d3-geo-projection
// Examples are d3.geoMercator, d3.geoAlbers
const projection = d3.geoAlbersUsa();
projection.fitSize([width, height], usStates);

// projection maps from world coordinates to svg coordinates
// projection([lon, lat]) returns an [x, y]

const path = d3.geoPath().projection(projection);

svg
.selectAll("path")
.data(usStates.features)
.enter()
.append("path")
.attr("fill", "none")
.attr("stroke", "#333")
.attr("d", path);

const rScale = d3
.scaleLinear()
.domain(d3.extent(usCities, (d) => Math.sqrt(d.population)))
.range([1, 20]);

// Try to place usCities on the map.
// You can compute the position of each city using projeciton([d.lon, d.lat]), which returns an [x, y] array.
svg
.selectAll("circle")
.data(usCities)
.enter()
.append("circle")
// Fill in the cx and cy so that the cities end up in the right position.
.attr("cx", (d) => projection([d.lon, d.lat])[0])
.attr("cy", (d) => {
return projection([d.lon, d.lat])[1];
})
// Update the radius based on the population
.attr("r", (d) => rScale(Math.sqrt(d.population)))
.style("fill", "yellow")
.style("stroke", "gray")
.style("stroke-width", 0.25)
.style("opacity", 0.75);

// Bonus: add a tooltip to the cities.
// Tefer to the Interaction to Event Handlers Notebook for an example of how to do this.
// https://observablehq.com/@kerzner/intro-to-event-handlers

return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
const width = 600;
const height = 600;

const svg = d3.create("svg").attr("width", width).attr("height", height);

// Use a hex bin map of each state from here: https://github.com/donmeltz/US-States---Hexbins
// Note: the data area already projected.
const projection = d3
.geoIdentity()
.reflectY(true)
.fitSize([width, height], usHex);

// Define quantize scale to sort data values into buckets of color
// You can experiment with other colormaps here as well.
const color = d3
.scaleQuantize()
.range([
"rgb(237,248,233)",
"rgb(186,228,179)",
"rgb(116,196,118)",
"rgb(49,163,84)",
"rgb(0,109,44)"
]);
//Colors derived from ColorBrewer, by Cynthia Brewer, and included in
//https://github.com/d3/d3-scale-chromatic

// Set up the
color.domain([
d3.min(usAgProductivity, (d) => d.value),
d3.max(usAgProductivity, (d) => d.value)
]);

const path = d3.geoPath().projection(projection);

// Merge the ag. data and GeoJSON
// Loop through once for each ag. data value
for (let i = 0; i < usAgProductivity.length; i++) {
//Grab state name
const dataState = usAgProductivity[i].state;
//Grab data value, and convert from string to float
const dataValue = usAgProductivity[i].value;
//Find the corresponding state inside the GeoJSON
for (let j = 0; j < usHex.features.length; j++) {
const jsonState = usHex.features[j].properties.Name;
if (dataState == jsonState) {
//Copy the data value into the JSON
usHex.features[j].properties.value = dataValue;
//Stop looking through the JSON
break;
}
}
}

const tooltip = d3
.select("body")
.append("div")
.style("position", "absolute")
.style("visibility", "hidden")
.style("background", "white");

// nodes

// .on("mousemove", (event, d) => {
// // Keep the tooltip aligned with the mouse as we move it.
// tooltip
// .style("top", event.clientY - 10 + "px")
// .style("left", event.clientX + 10 + "px");
// })
// .on("mouseout", (event, d) => {
// // As the mouse leaves, we want to remove the tooltip
// tooltip.style("visibility", "hidden");
// });

svg
.selectAll("path")
.data(usHex.features)
.enter()
.append("path")
.attr("stroke", "steelblue")
.attr("fill", (d) => color(d.properties.value))
.attr("d", path)
.on("mouseover", (event, d) => {
// When the mouse enters a circle, draw the tooltip.
d3.select(event.target).style("stroke-width", "2px");
tooltip.style("visibility", "visible");
tooltip.html(
`<ul><li>${d.properties.Name}</li><li>${d.properties.value}</li></ul>`
);
})
.on("mousemove", (event, d) => {
// Keep the tooltip aligned with the mouse as we move it.
tooltip
.style("top", event.clientY - 10 + "px")
.style("left", event.clientX + 10 + "px");
});

return svg.node();
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more