Published
Edited
May 23, 2021
Fork of Maps
Insert cell
Insert cell
nycGeo
Insert cell
Insert cell
nycGeo.features[0]
Insert cell
Insert cell
getZip = feature => feature.properties.zcta
Insert cell
getZip(nycGeo.features[0])
Insert cell
Insert cell
margin = ({top: 10, right: 0, bottom: 0, left: 10})
Insert cell
mapWidth = 640 - margin.left - margin.right
Insert cell
mapHeight = 640 - margin.top - margin.bottom
Insert cell
Insert cell
projection = d3.geoAlbers()
.fitSize([mapWidth, mapHeight], nycGeo)
Insert cell
path = d3.geoPath().projection(projection)
Insert cell
Insert cell
path(nycGeo)
Insert cell
path(nycGeo).length
Insert cell
Insert cell
path(nycGeo.features[0])
Insert cell
Insert cell
{
// set up
const svg = d3.create('svg')
.attr('width', mapWidth + margin.left + margin.right)
.attr('height', mapHeight + margin.top + margin.bottom);

const g = svg.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
// draw map

// draw one svg path per zip code
g.selectAll("path")
.data(nycGeo.features)
.join("path")
.attr("d", path)
.attr("fill", lightgray)
.attr("stroke", "white");

return svg.node();
}
Insert cell
Insert cell
zipToInjuries
Insert cell
maxInjuriesForZip = d3.max(Object.values(zipToInjuries))
Insert cell
Insert cell
color = d3.scaleSequential()
.domain([0, maxInjuriesForZip])
.interpolator(d3.interpolateBlues)
.unknown(lightgray)
Insert cell
Insert cell
{
const svg = d3.create('svg')
.attr('width', mapWidth + margin.left + margin.right)
.attr('height', mapHeight + margin.top + margin.bottom);

const g = svg.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
// draw map

g.selectAll("path")
.data(nycGeo.features)
.join("path")
.attr("d", path)
.attr("fill", d => color(zipToInjuries[getZip(d)]))
.attr("stroke", "white");

return svg.node();
}
Insert cell
Insert cell
maxRadius = 10
Insert cell
// we want to map number of requests to the area of the circle,
// so we use scaleSqrt since the area of a circle is pi * (r^2)
radius = d3.scaleSqrt()
.domain([0, maxInjuriesForZip])
.range([0, maxRadius])
Insert cell
Insert cell
path.centroid(nycGeo.features[0])
Insert cell
{
const svg = d3.create('svg')
.attr('width', mapWidth + margin.left + margin.right)
.attr('height', mapHeight + margin.top + margin.bottom);

const g = svg.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
// add legend

const legendGroup = g.append("g")
.attr('font-family', 'sans-serif')
.attr('font-size', 12);
legendGroup.append('text')
.text('Vehicle collision injuries, 2019')
const legendRows = legendGroup.selectAll("g")
.data([100, 200, 400, 800])
.join("g")
.attr("transform", (d, i) => `translate(0, ${15 + i * 2.5 * maxRadius})`);
legendRows.append("circle")
.attr("r", d => radius(d))
.attr("fill", "steelblue");

legendRows.append("text")
.attr("dominant-baseline", "middle")
.attr("x", maxRadius + 5)
.text(d => d);
// draw map

g.selectAll("path")
.data(nycGeo.features)
.join("path")
.attr("d", path)
.attr("fill", lightgray)
.attr("stroke", "white");

// draw circles

g.append("g")
.selectAll("circle")
.data(nycGeo.features)
.join("circle")
.attr("fill", "steelblue")
// set the position and size of the circles
.attr("transform", d => `translate(${path.centroid(d)})`)
.attr("r", d => radius(zipToInjuries[getZip(d)]));

return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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