Published
Edited
Mar 2, 2022
1 star
Insert cell
# starter map coney island
Insert cell
zips = FileAttachment("zips8.geojson").json()
Insert cell
nycparks = FileAttachment("parks8.geojson").json()
Insert cell
nycstreets = FileAttachment("streets2.geojson").json()
Insert cell
nycsubway = FileAttachment("subway.geojson").json()
Insert cell
nycstations = FileAttachment("subway station.geojson").json()
Insert cell
spreadsheet = "https://docs.google.com/spreadsheets/d/e/2PACX-1vS9HnzLa3MDUf5Z1mk-Xt8lPonNVV9Vl3ba_JpsGD_iQr2WXsFaqp3fKR77nfPdNJVQcLM6Bk69kp-9/pub?output=csv"
Insert cell
siteDot = d3.csv(spreadsheet, d3.autoType)
Insert cell
AttractionSpreadsheet = "https://docs.google.com/spreadsheets/d/e/2PACX-1vRR0l47Da6MVsFTu5xHWtp-goJZntnmTNIejTnL3yR6ZT9g5p18_scFshR5RAOumihUkXLhk8wJOsSU/pub?output=csv"
Insert cell
attraction = d3.csv(AttractionSpreadsheet, d3.autoType)
Insert cell
Foodspreadsheet = "https://docs.google.com/spreadsheets/d/e/2PACX-1vTA9waDP14PqJBxzvvE2dEjWIr2cAbar3E96sQitzPSwpCISO7zWmB-JTX01Xndtuqzf79KLee_78Z-/pub?output=csv"
Insert cell
Food = d3.csv(Foodspreadsheet, d3.autoType)
Insert cell
site = FileAttachment("rectangle site.geojson").json()
Insert cell
rectangle1 = FileAttachment("rectangle_maybe.geojson").json()
Insert cell
zoom = FileAttachment("ZOOM.geojson").json()
Insert cell
d3 = require("d3@6")
Insert cell
chart = {
const width = 960,
height = 900;
const svg = d3.create("svg")
.attr("viewBox", [-60, 0, width, height]);

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

var path = d3.geoPath().projection(projection);
var path2 = d3.geoPath().projection(projection);
var path3 = d3.geoPath().projection(projection);
var circle1 = d3.geoPath().projection(projection);

//insert parks
var g = svg.append("g").attr("id", "paths");
g.selectAll("path") //d3 geopath
//svg
//.selectAll('path')
.data(nycparks.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", "green")
.style('fill-opacity','.2')
.style("stroke-width", ".5")
.style("stroke", "green")
.on('mouseover', addFill)
.on('mouseleave', removeFill)


// hover park name and fill
function addFill(event,d) {
d3.select(this).style("fill", "blue")
d3.select(this).style('fill-opacity','.2')
svg
.append('text')
.attr('class', 'labels') //appends path to data
.attr('x', '50')
.attr('y', '700')
.attr("font-family", "Helvetica")
.attr('font-size', '1em')
.text(d.properties.park_name)
}

function removeFill(event,d) {
d3.selectAll('text.labels').remove()
d3.select(this).style("fill", "green")
d3.select(this).style('fill-opacity','.2')
}

//insert subway
//var g = svg.append("g").attr("id", "paths");
g.selectAll("path2") //d3 geopath
//svg
//.selectAll('path')
.data(nycsubway.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", "none")
.style('fill-opacity','0')
.style("stroke-width", "1")
.style("stroke", "red")


//insert street center lines
//var g = svg.append("g").attr("id", "paths");
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", "none")
.style('fill-opacity','.5')
.style("stroke-width", ".4")
.style("stroke", "gray")



// subway stations
var cir = svg.append("g").attr("id", "paths");
cir.selectAll("circle") //d3 geopath
//svg
//.selectAll('path')
.data(nycstations.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', 'red')
.style("fill", "red")
.style('fill-opacity','.5')
.style("stroke-width", "1")


// site dot
//var g = svg.append("g").attr("id", "paths");
g.selectAll("circle") //d3 geopath
//svg
//.selectAll('path')
.data(siteDot) //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 projection([d.long,d.lat])[0]})
.attr("cy",function(d) {return projection([d.long,d.lat])[1]})
.attr('r', 6)
.attr('fill', 'black')
.style('fill-opacity','.9')
.style("stroke-width", "1")


// site text
var t = svg.selectAll('text')
t.enter().append('text')
.data(siteDot)
.enter()
.append('text')
.attr('class','annotation')
.attr('x','50')
.attr('y','750')
.attr("font-family", "Helvetica")
.attr('font-size','.75em')
.attr('fill','rgb(50,50,50)')
//.attr('text-anchor','end')
//.text(function(d){return d.address})
.text(function(d){return d.Address})

var t = svg.selectAll('text')
t.enter().append('text')
.data(siteDot)
.enter()
.append('text')
.attr('class','siteDescription')
.attr('x','50')
.attr('y','770')
.attr("font-family", "Helvetica")
.attr('font-size','.5em')
.attr('fill','rgb(50,50,50)')
//.attr('text-anchor','end')
//.text(function(d){return d.address})
.text(function(d){return d.Description})

var wrap = svg.selectAll("text.siteDescription")
.each(function(d, i) { wrap_text(d3.select(this), 250) });
t.enter().append('text')
.data(siteDot)
.enter()
.append('text')
.attr('class','annotation')
.attr('x','50')
.attr('y','730')
.attr("font-family", "Helvetica")
.attr('font-size','1.25em')
.attr('fill','rgb(50,50,50)')
//.attr('text-anchor','end')
//.text(function(d){return d.address})
.text(function(d){return d.Name})


// site text annotation line
var ln = svg.append("g").attr("id", "paths");
cir = svg.selectAll("line")
.data(siteDot) //get data to define path
.enter()
.append('line')
.attr('class','sbLn')
.attr('x1','250')
.attr('y1','725')
.attr('x2',function(d) {return projection([d.long,d.lat])[0]})
.attr("y2",function(d) {return projection([d.long,d.lat])[1]})
.attr('stroke-width','.8')
.attr('stroke-opacity','1')
.style('stroke','rgb(0,0,0)')

svg
.append('line')
.attr('class','sbLn')
.attr('x1',200)
.attr('y1',725)
.attr('x2',250)
.attr('y2',725)
.attr('stroke-width','.8')
.attr('stroke-opacity','1')
.style('stroke','rgb(0,0,0)')
/*
// site rectangle
//var g = svg.append("g").attr("id", "paths");
g.selectAll("path2") //d3 geopath
//svg
//.selectAll('path')
.data(rectangle1.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", "1")
.style("stroke", "blue")
*/
// Insert Attractions POI
var cir2 = svg.append("g").attr("id", "paths");
cir2.selectAll("circle") //d3 geopath
//svg
//.selectAll('path')
.data(attraction) //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 projection([d.Long,d.Lat])[0]})
.attr("cy",function(d) {return projection([d.Long,d.Lat])[1]})
.attr('r', 3)
.attr('fill', 'pink')
.style('fill-opacity','.9')
.style("stroke-width", "1")
.on('mouseover', poiAttraction)
.on('mouseout', poiErase)

// mouse over function for attractions
function poiAttraction(event, d) {
svg
.append("text") //appends path to data
.attr('class','pois')
.attr('x','50')
.attr('y','650')
.attr("font-family", "Helvetica")
.attr('font-size','.75em')
//.attr('text-anchor','end')
//.style("font-weight","bold")
.text(d.Name)
svg
.append("text") //appends path to data
.attr('class','pois')
.attr('x','50')
.attr('y','665')
.attr("font-family", "Helvetica")
.attr('font-size','.5em')
//.attr('text-anchor','end')
//.style("font-weight","bold")
.text(d.Description)
svg.append('line') //add line from POI point
.attr('class','pois')
.attr('x1','100')
.attr('y1','600')
.attr('x2',projection([d.Long,d.Lat])[0])
.attr("y2",projection([d.Long,d.Lat])[1])
.attr('stroke-width','.8')
.attr('stroke-opacity','.4')
.style('stroke','rgb(0,0,0)')
svg
.append('line') //add line from pixel location to pixel location
.attr('class','pois')
.attr('x1',100)
.attr('y1',600)
.attr('x2',100)
.attr('y2',630)
.attr('stroke-width','.8')
.attr('stroke-opacity','1')
.style('stroke','rgb(0,0,0)')
}

function poiErase(event, d) {
d3.selectAll('text.pois').remove()
d3.selectAll('line.pois').remove()
}

// Insert Food
var cir3 = svg.append("g").attr("id", "paths");
cir3.selectAll("circle") //d3 geopath
//svg
//.selectAll('path')
.data(Food) //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 projection([d.Long,d.Lat])[0]})
.attr("cy",function(d) {return projection([d.Long,d.Lat])[1]})
.attr('r', 3)
.attr('fill', 'orange')
.style('fill-opacity','.9')
.style("stroke-width", "1")
.on('mouseover', poiText)
.on('mouseout', poiErase1)

// mouseover function for food
function poiText(event, d) {
svg
.append("text") //appends path to data
.attr('class','pois')
.attr('x','50')
.attr('y','650')
.attr("font-family", "Helvetica")
.attr('font-size','.75em')
//.attr('text-anchor','end')
//.style("font-weight","bold")
.text(d.Name)
svg
.append("text") //appends path to data
.attr('class','pois')
.attr('x','50')
.attr('y','665')
.attr("font-family", "Helvetica")
.attr('font-size','.5em')
//.attr('text-anchor','end')
//.style("font-weight","bold")
.text(d.Description)
svg.append('line') //add line from POI point
.attr('class','pois')
.attr('x1','100')
.attr('y1','600')
.attr('x2',projection([d.Long,d.Lat])[0])
.attr("y2",projection([d.Long,d.Lat])[1])
.attr('stroke-width','.8')
.attr('stroke-opacity','.4')
.style('stroke','rgb(0,0,0)')
svg
.append('line') //add line from pixel location to pixel location
.attr('class','pois')
.attr('x1',100)
.attr('y1',600)
.attr('x2',100)
.attr('y2',630)
.attr('stroke-width','.8')
.attr('stroke-opacity','1')
.style('stroke','rgb(0,0,0)')
var wrap = svg.selectAll("text.pois")
.each(function(d, i) { wrap_text(d3.select(this), 250) });
}

function poiErase1(event, d) {
d3.selectAll('text.pois').remove()
d3.selectAll('line.pois').remove()
}
// zipcodes
//var g = svg.append("g").attr("id", "paths");
g.selectAll("path3") //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
.style("fill", "none")
.style('fill-opacity','.5')
.style("stroke-width", ".3")
.style("stroke", "black")
/*
// add line from pixel location to another pixel location
svg
.append('line')
.attr('class', 'pois')
.attr('x1',373)
.attr('y1',)
*/

// add line from site point



return svg.node();
}
Insert cell
import { wrap_text, wrap_text_nchar } from "@ben-tanen/svg-text-and-tspan-word-wrapping"
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