Public
Edited
Jul 23, 2024
Insert cell
Insert cell
chart = {
const width = 900,//pixel size of the map
height = 900;
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width-50, height-10]);

// Use Mercator projection
var projection = d3
.geoMercator()//projection system used
.fitSize([width, height], boundingBox);

var path = d3.geoPath().projection(projection);//need one of these for each line layer from qgis
var path2 = d3.geoPath().projection(projection);
var path3 = d3.geoPath().projection(projection);
var path4 = d3.geoPath().projection(projection);
var path5 = d3.geoPath().projection(projection);
var path6 = d3.geoPath().projection(projection);
var path7 = d3.geoPath().projection(projection);
var path8 = d3.geoPath().projection(projection);

var g = svg.selectAll('g').attr("id", "paths");//qgis lines variable //one variable for each geometry type
var c = svg.selectAll("circle")//for circles
var p = svg.selectAll("polyline")//for polylines from rhino
var t = svg.selectAll("text")
var l = svg.selectAll("line")





//lines from rhino


function polyline(data, sfill, sOpac, sW, stroke){

g.enter().append("polyline")
.data(data) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", function(d){return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", sfill)
.style('stroke-opacity',sOpac)
.style("stroke-width", sW)
.style("stroke", stroke)

}
g.enter().append("polyline")
.data(manhttan2) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", function(d){return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", 'black')
.style('fill-opacity','1')
.style("stroke-width", "1")
.style("stroke", 'white')

g.enter().append("polyline")
.data(background) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", function(d){return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "rgb(40,40,40)")
.style('fill-opacity','1')
.style("stroke-width", "1")
.style("stroke", 'white')

p.enter().append("polyline")
.data(drone4) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", function(d){return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", 'none')
.style('fill-opacity','1')
.style("stroke-width", "1")
.style("stroke", 'white')

p.enter().append("polyline")
.data(title) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", function(d){return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", 'white')
.style('fill-opacity','1')
.style("stroke-width", ".3")
.style("stroke", 'white')

p.enter().append("polyline")
.data(titleFill) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", function(d){return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", 'black')
.style('fill-opacity','1')
.style("stroke-width", ".3")
.style("stroke", 'white')

p.enter().append("polyline")
.data(icon4) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", function(d){return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", 'none')
.style('fill-opacity','1')
.style("stroke-width", "4")
.style("stroke", 'white')

p.enter().append("polyline")
.data(droneRoutes3) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", function(d){return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", 'white')
.style('fill-opacity','1')
.style("stroke-width", ".3")
.style("stroke", 'white')

polyline(dogParksToCanineWaste,'blue','1','1','cyan')
//g.enter().append("polyline")
//.data(manhattanCenter) //get data to define path
//.enter() //there are more data than elements, this selects them
//.append('polyline')
// .attr("points", function(d){return d}) //The d attribute defines a path to be drawn, only applies to appended elements
//.style("fill", sfill)
//.style('stroke-opacity',sOpac)
//.style("stroke-width", "1")
//.style("stroke", 'white')


//Display Names from Spreadsheet
t.enter().append('text')
.data(dogparks) //get data to define path
.enter() //there are more data than elements, this selects them
.append("text") //appends path to data
//.attr('class','spots')
.attr('x',155)
.attr("y",function(d,i){return 700 + (i*15)})
.attr('fill', 'white ')
.style('font-family','chalkduster')
.style("font-size", "7px")
.style("text-anchor", "end")
.text(function(d){return d.Name})
.on("mouseover",dogText)
.on("mouseout",removedogText)
function removedogText(event,d){
svg.selectAll("line.dogLine").remove()
}
function dogText(event,d){
//Lines to annotate
l.enter().append('line')
.data(dogparks) //get data to define path
.enter() //there are more data than elements, this selects them
.append("line") //appends path to data
.attr('class','dogLine')
.attr('x1',150)
.attr("y1",700)
.attr('x2',projection([d.Long,d.Lat])[0]-5)
.attr("y2",projection([d.Long,d.Lat])[1])
.attr('stroke', 'yellow')
.attr('stroke-width', '1.25')
.style('stroke-dasharray', '3 2')
//Lines to annotate
l.enter().append('line')
.data(dogparks) //get data to define path
.enter() //there are more data than elements, this selects them
.append("line") //appends path to data
.attr('class','dogLine')
.attr('x1',150)
.attr("y1",function(d,i){return 700 + (i*15)})
.attr('x2',function(d) {return projection([d.Long,d.Lat])[0]-5})
.attr("y2",function(d,i){return 700 + (i*15)})
.attr('stroke', 'grey')
.attr('stroke-width', '.5')
.style('stroke-dasharray', '3 2')

l.enter().append('line')
.data(dogparks) //get data to define path
.enter() //there are more data than elements, this selects them
.append("line") //appends path to data
.attr('class','dogLine')
.attr('x1',function(d) {return projection([d.Long,d.Lat])[0]-5})
.attr("y1",function(d,i){return 700 + (i*15)} )
.attr('x2',function(d) {return projection([d.Long,d.Lat])[0]-5})
.attr("y2",function(d) {return projection([d.Long,d.Lat])[1]+10})
.attr('stroke', 'grey')
.attr('stroke-width', '.5')
.style('stroke-dasharray', '3 2')
}

p.enter().append("polyline")
.data(zone6) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", function(d) {return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", 'white')
.style('fill-opacity','0')
.style("stroke-width", '0')
.style("stroke", 'white')
.style('stroke-dasharray','5 5')
.on("mouseover", addWireframe3)
.on("mouseout", removeWireframe3)

function addWireframe3(event,d){
p.enter().append("polyline")
.data(wireframe3) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr('class','wireframe3')
.attr("points", function(d) {return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", 'none')
//.style('fill-opacity','0')
.style("stroke-width", '2')
.style("stroke", 'orange')
//.style('stroke-dasharray','5 5')
}
function removeWireframe3(event,d){
svg.selectAll('polyline.wireframe3').remove()

}

p.enter().append("polyline")
.data(zone2) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", function(d) {return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", 'white')
.style('fill-opacity','0')
.style("stroke-width", '0')
.style("stroke", 'white')
.style('stroke-dasharray','5 5')
.on("mouseover", addBarker2)
.on("mouseout", removeBarker2)

function addBarker2(event,d){
p.enter().append("polyline")
.data(barker2) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr('class','barker2')
.attr("points", function(d) {return d}) //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", 'white')
//.style('stroke-dasharray','5 5')
}
function removeBarker2(event,d){
svg.selectAll('polyline.barker2').remove()

}

//points from spreadsheet
c.enter().append('circle')
.data(subwaystops) //get data to define path
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr('class','spots')
.attr('cx',function(d) {return projection([d.Long,d.Lat])[0]-5})
.attr("cy",function(d) {return projection([d.Long,d.Lat])[1]+10})
.attr('r', 6)
.attr('fill', 'red')
.style('fill-opacity','1')
.style("stroke-width", "1")
.style("stroke", "white")
.on("mouseover", addText)
.on("mouseout", removeText)


function addText(event,d){

svg
.append("text") //appends path to data
.attr('class','sText')
.attr('x',projection([d.Long,d.Lat])[0])
.attr("y",projection([d.Long,d.Lat])[1]-30)
.attr('r', 6)
.attr('fill', 'white')
.style('font-family','chalkduster')
.style("font-size", "15px")
.style("stroke", "white")
.text(d.Name)

svg
.append("text") //appends path to data
.attr('class','sText')
.attr('x',600)
.attr("y",750)
.attr('r', 6)
.attr('fill', 'white')
.style('font-family','chalkduster')
.style("font-size", "9 px")
.style("stroke", "White")
.text(d.Description)

var wrap = svg.selectAll("text.sText")
.each(function(d, i) { wrap_text(d3.select(this), 100) });
}

function removeText(){
svg.selectAll('text.sText').remove()

}

//static lines from qgis
staticLines(path4, parks.features,"rgb(200,225,200)",'.1','.1',"rgb(0,255,0)")
staticLines(path5 , centeriline.features,"none",'.25','.6',"rgb(255,255,255)")
staticLines(path8 , dogRuns2.features,"rgb(200,255,255)",'.25','.6',"rgb(0,255,0)")
function staticLines(path, data, sfill, sOpac, sW, stroke){

g.enter().append("path")
.data(data) //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", sfill)
.style('stroke-opacity',sOpac)
.style("stroke-width", sW)
.style("stroke", stroke)

}


//static points from qgis
staticCircles(mta2.features,'4','red','1',"0")
staticCircles(canineWaste.features,'4','blue','1',"0")

function staticCircles(data,r,sfill, sOpac, sWidth){

c.enter().append('circle')
.data(data) //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', r)
.attr('fill', sfill)
.style('fill-opacity',sOpac)
.style("stroke-width", sWidth)
}

g.enter().append("polyline")
.data(bottomback) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", function(d){return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "rgb(40,40,40)")
.style('fill-opacity','1')
.style("stroke-width", "0")
.style("stroke", 'white')


g.enter().append("polyline")
.data(blueball) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", function(d){return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "cyan")
.style('fill-opacity','1')
.style("stroke-width", "0")
.style("stroke", 'white')

g.enter().append("polyline")
.data(blueball2) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", function(d){return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "cyan")
.style('fill-opacity','1')
.style("stroke-width", "0")
.style("stroke", 'white')
g.enter().append("polyline")
.data(yellowball) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", function(d){return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "yellow")
.style('fill-opacity','1')
.style("stroke-width", "0")
.style("stroke", 'white')

g.enter().append("polyline")
.data(yellowball2) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", function(d){return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "yellow")
.style('fill-opacity','1')
.style("stroke-width", "0")
.style("stroke", 'white')

g.enter().append("polyline")
.data(orangeball) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", function(d){return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "orange")
.style('fill-opacity','1')
.style("stroke-width", "0")
.style("stroke", 'white')

g.enter().append("polyline")
.data(orangeball2) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", function(d){return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "orange")
.style('fill-opacity','1')
.style("stroke-width", "0")
.style("stroke", 'white')
g.enter().append("polyline")
.data(whiteball) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", function(d){return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "white")
.style('fill-opacity','1')
.style("stroke-width", "0")
.style("stroke", 'white')

p.enter().append("polyline")
.data(ozone2) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", function(d) {return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", 'none')
.style('fill-opacity','0')
.style("stroke-width", '0')
.style("stroke", 'white')
.style('stroke-dasharray','5 5')
.on("mouseover", addOp2)
.on("mouseout", removeOp2)

function addOp2(event,d){
p.enter().append("polyline")
.data(op2) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr('class','op2')
.attr("points", function(d) {return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", 'orange')
//.style('fill-opacity','0')
.style("stroke-width", '1')
.style("stroke", 'white')
//.style('stroke-dasharray','5 5')
}
function removeOp2(event,d){
svg.selectAll('polyline.op2').remove()

}
//draw icons at spreadsheet location
p.enter().append("polyline")
.data(dogparks ) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", doggy3) //The d attribute defines a path to be drawn, only applies to appended elements
.attr('transform',function(d) {return 'translate('+projection([d.Long,d.Lat])[0]+','+ (projection([d.Long,d.Lat])[1]+ 15) + ')';
})
.style("fill", ' cyan')
.style("stroke-width", '0.5')
.style("stroke", 'blue' )
.on("mouseover", addText)
.on("mouseout", removeText)

return svg.node();
}

Insert cell
op2 = FileAttachment("op2.txt").tsv({array:true})
Insert cell
ozone2 = FileAttachment("Ozone2.txt").tsv({array:true})
Insert cell
orangepaws = FileAttachment("orangepaws.txt").tsv({array:true})
Insert cell
ozone = FileAttachment("Ozone.txt").tsv({array:true})
Insert cell
yellowball2 = FileAttachment("yellowball2.txt").tsv({array:true})
Insert cell
orangeball2 = FileAttachment("orangeball2.txt").tsv({array:true})
Insert cell
blueball2 = FileAttachment("blueball2.txt").tsv({array:true})
Insert cell
whiteball = FileAttachment("whiteball.txt").tsv({array:true})
Insert cell
orangeball = FileAttachment("orangeball.txt").tsv({array:true})
Insert cell
yellowball = FileAttachment("yellowball.txt").tsv({array:true})
Insert cell
blueball = FileAttachment("blueball.txt").tsv({array:true})
Insert cell
bottomback = FileAttachment("bottomback.txt").tsv({array:true})
Insert cell
droneRoutes2 = FileAttachment("Drone Routes2.txt").tsv({array:true})
Insert cell
zone5 = FileAttachment("zone5.txt").tsv({array:true})
Insert cell
icon3 = FileAttachment("Icon3.txt").tsv({array:true})
Insert cell
barker2 = FileAttachment("barker2.txt").tsv({array:true})
Insert cell
zone4 = FileAttachment("zone 4.txt").tsv({array:true})
Insert cell
zone3 = FileAttachment("zone 3.txt").tsv({array:true})
Insert cell
leash = FileAttachment("Leash.txt").tsv({array:true})
Insert cell
zone2 = FileAttachment("zone 2.txt").tsv({array:true})
Insert cell
barker = FileAttachment("barker.txt").tsv({array:true})
Insert cell
wireframe3 = FileAttachment("Wireframe3.txt").tsv({array:true})
Insert cell
drone4 = FileAttachment("Drone 4.txt").tsv({array:true})
Insert cell
drone2 = FileAttachment("Drone2.txt").tsv({array:true})
Insert cell
doneout = FileAttachment("DoneOut.txt").tsv({array:true})
Insert cell
wireframe2 = FileAttachment("wireframe2.txt").tsv({array:true})
Insert cell
manhttan2 = FileAttachment("manhttan2.txt").tsv({array:true})
Insert cell
doggy3 = FileAttachment("doggy3.txt").tsv({array:true})
Insert cell
zone1 = FileAttachment("zone1@1.txt").tsv({array:true})
Insert cell
droneRoutes = FileAttachment("Drone Routes@1.txt").tsv({array:true})
Insert cell
icon = FileAttachment("Icon@1.txt").tsv({array:true})
Insert cell
titleFill = FileAttachment("Title Fill@1.txt").tsv({array:true})
Insert cell
title = FileAttachment("Title@1.txt").tsv({array:true})
Insert cell
drone = FileAttachment("Drone@1.txt").tsv({array:true})
Insert cell
background = FileAttachment("Background@1.txt").tsv({array:true})
Insert cell
manhattanCenter = FileAttachment("Manhattan Center@1.txt").tsv({array:true})
Insert cell
manhattan = FileAttachment("Manhattan@1.txt").tsv({array:true})
Insert cell
dogBone = FileAttachment("Dog Bone@1.txt").tsv({array:true})
Insert cell
Insert cell
dogparks = d3.csv(dogparklink,d3.autoType)
Insert cell
Insert cell
subwaystops = d3.csv(subwaylink,d3.autoType)
Insert cell
subwaysToDogParks = FileAttachment("Subways to Dog PArks@1.txt").tsv({array:true})
Insert cell
dogParksToCanineWaste = FileAttachment("Dog Parks to Canine Waste@1.txt").tsv({array:true})
Insert cell
mta2 = FileAttachment("MTA2@1.geojson").json()
Insert cell
dogRuns2 = FileAttachment("Dog Runs 2@1.geojson").json()
Insert cell
canineWaste = FileAttachment("Canine Waste@1.geojson").json()
Insert cell
boundingBox = FileAttachment("Bounding Box@1.geojson").json()
Insert cell
parks = FileAttachment("PArks@1.geojson").json()
Insert cell
Insert cell
spots = d3.csv(spotsLink,d3.autoType)
Insert cell
import { wrap_text, wrap_text_nchar } from "@ben-tanen/svg-text-and-tspan-word-wrapping"
Insert cell
centeriline = FileAttachment("Centeriline@1.geojson").json()
Insert cell
icon2 = FileAttachment("Icon2@1.txt").tsv({array:true})
Insert cell
doggy2 = FileAttachment("doggy2.txt").tsv({array:true})
Insert cell
zone6 = FileAttachment("zone6.txt").tsv({array:true})
Insert cell
icon4 = FileAttachment("icon4.txt").tsv({array:true})
Insert cell
droneRoutes3 = FileAttachment("Drone Routes3.txt").tsv({array:true})
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