Published
Edited
Jun 19, 2022
Fork of starter map
Insert cell
# NYC Sea Level Threats
Insert cell
eva_cent =FileAttachment("Hurricane Evacuation Centers (1).geojson").json()
Insert cell
zips = FileAttachment("zip_test4.geojson").json()
Insert cell
nycsub = FileAttachment("subway_lines-2.geojson").json()
Insert cell
shoreline = FileAttachment("shoreline@1.geojson").json()
Insert cell
slr_10ft = FileAttachment("slr_10ft.geojson").json()
Insert cell
nycStreets = FileAttachment("test street.geojson").json()
Insert cell
d3 = require("d3@6")
Insert cell
chart = {
const width = 960,
height = 900;
const svg = d3
.create("svg")
.attr("viewBox", [0, 0, width, height])
.attr("viewBox", [-15, -10, width, height])
.style("background", "#284270");

// Use Mercator projection
var projection = d3.geoMercator().fitSize([width - 50, height - 50], zips);
var path = d3.geoPath().projection(projection);
var path2 = d3.geoPath().projection(projection);

//add lines
svg
.selectAll("line")
.data(eva_cent.features)
.enter()
.append("line")
.attr("x1", function (d) {
return path.centroid(d)[0];
})
.attr("y1", function (d) {
return path.centroid(d)[1];
})
.attr("x2", 100)
.attr("y2", function (d, i) {
return i * 10 + 10;
})
.attr("stroke-width", ".8")
.attr("stroke-opacity", ".15")
.style("stroke", "white");

var g = svg.append("g").attr("id", "paths");
g.selectAll("path") //d3 geopath
//svg
//.selectAll('path')
.data(zips.features) //get data to define path
.enter() //there are more data than elements, this selects them
.append("path") //appends path to data
.attr("class", "outlines")
.attr("d", path) //The d attribute defines a path to be drawn, only applies to appended elements

//population
.attr("fill", (d) => color(d.properties.POPULATION))
.style("fill-opacity", ".5")
.style("stroke-width", ".35")
.style("stroke", "#ccc");

g.selectAll("path2") //d3 geopath
//svg
//.selectAll('path')
.data(nycStreets.features) //get data to define path
.enter() //there are more data than elements, this selects them
.append("path") //appends path to data
.attr("class", "outlines")
.attr("d", path) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill-opacity", "0")
.style("stroke-width", ".05")
.style("stroke", "black");

//shoreline
g.selectAll("path") //d3 geopath
//svg
//.selectAll('path')
.data(shoreline.features) //get data to define path
.enter() //there are more data than elements, this selects them
.append("path") //appends path to data
.attr("class", "outlines")
.attr("d", path) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill-opacity", "0")
.style("stroke-width", ".15")
.style("stroke", "black");

//subline
g.selectAll("path2") //d3 geopath
//svg
//.selectAll('path')
.data(nycsub.features) //get data to define path
.enter() //there are more data than elements, this selects them
.append("path") //appends path to data
.attr("class", "outlines")
.attr("d", path) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill-opacity", "0")
.style("stroke-width", ".35")
.style("stroke", "red");

//evaluation_stroke
g.selectAll("path2") //d3 geopath
//svg
//.selectAll('path')
.data(eva_cent.features) //get data to define path
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr("cx", function (d) {
return path.centroid(d)[0];
})
.attr("cy", function (d) {
return path.centroid(d)[1];
})
.attr("r", 42)
.style("stroke-width", ".05")
.style("stroke", "grey")
.attr("fill", "purple")
.style("fill-opacity", ".1");

//evaluation
g.selectAll("path2") //d3 geopath
//svg
//.selectAll('path')
.data(eva_cent.features) //get data to define path
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr("cx", function (d) {
return path.centroid(d)[0];
})
.attr("cy", function (d) {
return path.centroid(d)[1];
})
.attr("r", 3)
.attr("fill", "purple")
.style("fill-opacity", ".5")
.on("mouseover", addBox)
.on("mouseout", removeBox);

svg
.selectAll("text")
.data(eva_cent.features)
.enter()
.append("text")
.attr("x", "0")
.attr("y", function (d, i) {
return i * 10 + 10;
})
.style("font", "8px roboto")
.style("fill", "white")
.attr("font-size", ".55em")
.attr("text-anchor", "start")
.text(function (d) {
return d.properties.bldg_name;
});

//slr_10ft
g.selectAll("path2") //d3 geopath
//svg
//.selectAll('path')
.data(slr_10ft.features) //get data to define path
.enter() //there are more data than elements, this selects them
.append("path") //appends path to data
.attr("class", "outlines")
.attr("d", path) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "blue")
.style("fill-opacity", ".5")
.style("stroke-width", "0")
.on("mouseover", addFill)
.on("mouseleave", removeFill);

//add slr_labals
function addFill(event, d) {
d3.select(this).style("fill", "red");
d3.select(this).style("fill-opacity", ".5");

svg
.append("text")
.attr("class", "labels")
.attr("x", "830")
.attr("y", "10")
.style("font", "12px roboto")
.style("fill", "white")
.attr("font-size", ".85em")
.text("sea level rise 10ft");
}

//take slr_labals away
function removeFill(event, d) {
d3.selectAll("text.labels").remove();
d3.select(this).style("fill", "blue");
d3.select(this).style("fill-opacity", ".2");
}

//add evacuation_site stop tool tip
var tooltip = svg.append("g");
function addBox(event, d) {
var centroid = path.centroid(d);
tooltip.call(
callout,
`${d.properties.bldg_name}
${d.properties.bldg_add}, ${d.properties.city}, ${d.properties.state}`
);
tooltip.attr("transform", "translate(" + centroid + ")");
}

function removeBox(event, d) {
tooltip.call(callout, null);
}

// add title
svg
.append("text")
.attr("x", "520")
.attr("y", "830")
.attr("font-size", "1.35em")
.style("font", "24px roboto")
.attr("font-weight", "bold")
.style("fill", "#ef5454")
.text("NYC Sea Level Threats");

svg
.append("text")
.attr("x", "520")
.attr("y", "847")
.attr("font-size", ".6em")
.style("font", "10px roboto")
.style("fill", "#ef5454")
.text(
"the map indicates the predicted situation of 10ft sea level rising"
);

svg
.append("text")
.attr("x", "520")
.attr("y", "856")
.attr("font-size", ".6em")
.style("font", "10px roboto")
.style("fill", "#ef5454")
.text(
"with the present location of the evacuation center, public transportation system, and population."
);

return svg.node();
}
Insert cell
callout = (g, value) => {
if (!value) return g.style("display", "none");

g
.style("display", null)
.style("pointer-events", "none")
.style("font", "10px sans-serif");

const path = g.selectAll("path")
.data([null])
.join("path")
.attr("fill", "white")
.attr("stroke", "white");

const text = g.selectAll("text")
.data([null])
.join("text")
.call(text => text
.selectAll("tspan")
.data((value + "").split(/\n/))
.join("tspan")
.attr("x", 0)
.attr("y", (d, i) => `${i * 1.1}em`)
.style("font-weight", (_, i) => i ? null : "bold")
.text(d => d));

const {x, y, width: w, height: h} = text.node().getBBox();

text.attr("transform", `translate(${-w / 2},${15 - y})`);
path.attr("d", `M${-w / 2 - 10},5H-5l5,-5l5,5H${w / 2 + 10}v${h + 20}h-${w + 20}z`);
}
Insert cell
color = d3.scaleQuantize([1, 100000], d3.schemeBlues[9])
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