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

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