Public
Edited
Jul 31, 2024
Insert cell
Insert cell
chart = {
const width = 1000,//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], cbox);//our bounding box is here

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 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")


//static lines from qgis
//staticLines(path3, subways.features,"none",1,.5,"rgb(180,180,180)")

//staticLines(path5, dining_lines.features,"none",'1','.25',"rgb(255,0,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','outline')
.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)
}
function polyline(data, sfill, sOpac, sW, stroke,class1, dasharray){

g.enter().append("polyline")
.data(data) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr('class','class1')
.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)
.style('stroke-dasharray', dasharray)
}
//polyline(dronelogo2,'rgb(44, 44, 44)','80','2','none')
polyline(background1,'rgb(44, 44, 44)','1','1',' none')
polyline(watershade3,'rgb(135,206,250, 0.05)','1','2','rgb(135,206,235,0.05)','zzz')
polyline(waterbody,'rgb(86, 145, 153,0.3)','1','1',' none','zzz')
polyline(waterboundary,'rgb(86, 145, 153,0.3)','1','2','rgb(135,206,235,0.3)','zzz')
polyline(backdropCircle,'rgb(45, 52, 51,0.5)','2','1.7','rgb(160, 146, 170, 0.5)','zzz')

polyline(smallerFlyingZone,'rgb(156, 123, 134, 0.5)','1','1','none','zzz')
polyline(dronePath02,'rgb(185, 185, 247,0.7)','1','1','rgb(114, 174, 163, 0.8)','2 2','zzz')
//polyline(dronePath03,'rgb(120, 210, 187, 0.7)','1','1',' rgb(191, 191, 255, 0.7)','1 1')
polyline(dronePath04,'rgb(120, 210, 187. 0.7)','1','1',' rgb(191, 191, 255)','2 2','class1')
polyline(dronePath05,'rgb(120, 210, 187, 0.7)','1','1',' rgb(191, 191, 255)','2 2','zzz')
polyline(dronePathLoop,'none','1','5',' rgb(30,144,255, 0.5)', '10 10','class1')
//polyline(shade1,'rgb(86, 145, 153,0.05)','1','1',' none')
//polyline(shade2,'rgb(86, 145, 153,0.07)','1','1',' none')

polyline(rangeOfFlight,'rgb(196, 140, 158,0.2)','1','1',' white','zzz')
polyline(mainFlyingPoints,'rgb(150, 134, 161, 0.6)','2','6','rgb(160, 146, 170, 0.3)','zzz')


//polyline(vortex,'white','1','1','rgb(194, 194, 194, 0.05')

p.enter().append("polyline")
.data(vortex) //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("none", 'white')
.style('fill-opacity','10')
.style("stroke-width", '1')
.style("stroke", 'white')
.style("fill", 'rgb(194, 194, 194)')
//Corner Text
p.enter().append("polyline")
.data(cornertext) //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("none", 'white')
.style('fill-opacity','0')
.style("stroke-width", '1')
.style("stroke", 'white')
.style("fill", 'rgb(194, 194, 194, 0.6)')
staticLines(path6, basemap01.features,"none",'1','.55',"rgb(154, 154, 154, 0.6)")
staticLines(path4, parks.features,"rgb(95,158,160,0.3)",'.25','0.1',"white")





//static points from qgis
//staticCircles(waterfront.features,'2','none','1',"0")
//staticCircles(theaters.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)
}


/* c.enter().append("polyline")
.data(restrooms) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", fan2) //The d attribute defines a path to be drawn, only applies to appended elements
.attr('transform',function(d) {return 'translate('+path.centroid(d)[0]+','+path.centroid(d)[1]+')'})
.style("none", 'white')
.style("stroke-width", '0.8')
.style("stroke", 'white')
.style("fill", 'rgb(152,251,152, 0.5)')
.on("mouseover",addText)
.on("mouseout",removeText)
/*/







//lines from rhino
//drawing of logos from rhino at location from the spread sheets
p.enter().append("polyline")
.data(drawparks) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr('class','fanicon')
.attr("points", fan1) //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]+')'})
.style("none", 'white')
.style("stroke-width", '0.8')
.style("stroke", 'white')
.style("fill", 'rgb(152,251,152, 0.3)')
.on("mouseover",addText)
.on("mouseout",removeText)

//edit to add more zones and wireframes, just make sure you channge the parameters
//for drawing the zone that you need to hover over to draw the wireframe
p.enter().append("polyline")
.data(zone1) //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("none", 'white')
.style('fill-opacity','0')
.style("stroke-width", '0.2')
.style("stroke", 'white')
.style("fill", 'white')
//.style('stroke-dasharray', '5 5')
.on("mouseover",addWireframe)
.on("mouseout",removeWireframe)
function addWireframe(event,d){

p.enter().append("polyline")
.data(wireframe1) //get data to define path
.enter()
.append('polyline')
.attr('class', 'wireframe')
.attr("points", function(d) {return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("none", 'white')
.style('fill-opacity','1')
.style("stroke-width", '0.8')
.style("stroke", 'white')
.style("fill", 'rgb(255,255,255, 0.4)')

//text beside wireframe 1

svg //draw description
.append("text") //appends path to data
.attr('class','parkText')
.attr('x',280)
.attr("y",400)
.attr('fill', 'rgb(95,158,160,0.9)')
.style('font-family','Cursive')
.style("font-weight", "Bold")
.style('font-style','italic')
.style("font-size", "12px")
.text('Every race is a chance to push the limits of what you thought was possible, both for the drone and for yourself.')
svg
.append("text") //appends path to data
.attr('class','parkText')
.attr('x',800)
.attr("y",200)
.attr('fill', 'rgb(95,158,160,0.9)')
.style('font-family','Cursive')
.style("font-weight", "Bold")
.style('font-style','italic')
.style("font-size", "12px")
.text('Drone racing is about precision, speed, and control. Its the closest you can get to experiencing the rush of flight without leaving the ground.')

svg
.append("text") //appends path to data
.attr('class','parkText')
.attr('x',780)
.attr("y",750)
.attr('fill', 'rgb(95,158,160,0.9)')
.style('font-family','Cursive')
.style("font-weight", "Bold")
.style('font-style','italic')
.style("font-size", "12px")
.text('To race drones is to embrace a new kind of freedom. You feel like youre breaking through the barriers of conventional sport.')
var wrap = svg.selectAll("text.parkText")
.each(function(d, i) { wrap_text(d3.select(this), 100) });
}

function removeWireframe(event,d){
svg.selectAll('polyline.wireframe').remove()
svg.selectAll('text.parkText').remove()

}



//Wireframe Two
//edit to add more zones and wireframes, just make sure you channge the parameters
//for drawing the zone that you need to hover over to draw the wireframe
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("none", 'white')
.style('fill-opacity','0')
.style("stroke-width", '0.2')
.style("stroke", 'white')
.style("fill", 'white')
//.style('stroke-dasharray', '5 5')
.on("mouseover",addWireframe2)
.on("mouseout",removeWireframe2)
function addWireframe2(event,d){

p.enter().append("polyline")
.data(wireframe2) //get data to define path
.enter()
.append('polyline')
.attr('class', 'wireframe2')
.attr("points", function(d) {return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("none", 'white')
.style('fill-opacity','1')
.style("stroke-width", '0.4')
.style("stroke", 'white')
.style("fill", 'rgb(255,255,255, 0.2)')


//text beside wireframe 2
svg //draw description
.append("text") //appends path to data
.attr('class','parkText')
.attr('x',40)
.attr("y",400)
.attr('fill', 'rgb(95,158,160,0.9)')
.style('font-family','Cursive')
.style("font-weight", "Bold")
.style('font-style','italic')
.style("font-size", "15px")
.text('Unleash the ultimate thrill with FPV drones designed for competitive racing! Experience heart-pounding speeds and razor-sharp precision as you soar through the sky like never before. Dominate the track and push the boundaries of possibility—your race to victory starts now!!!')


svg //draw description
.append("text") //appends path to data
.attr('class','parkText')
.attr('x',700)
.attr("y",400)
.attr('fill', 'rgb(95,158,160,0.7)')
.style('font-family','Cursive')
.style("font-weight", "Bold")
.style('font-style','italic')
.style("font-size", "25px")
.text('Feel the Adrenaline, Rule the Airwaves!')

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

}

function removeWireframe2(event,d){
svg.selectAll('polyline.wireframe2').remove()
svg.selectAll('text.parkText').remove()
}



//Wireframe Three
//Third interaction from rhino, drone flight route

//edit to add more zones and wireframes, just make sure you channge the parameters
//for drawing the zone that you need to hover over to draw the wireframe
p.enter().append("polyline")
.data(zone3) //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("none", 'white')
.style('fill-opacity','0')
.style("stroke-width", '0.2')
.style("stroke", 'white')
.style("fill", '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()
.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("none", 'white')
.style('fill-opacity','1')
.style("stroke-width", '0.4')
.style("stroke", 'white')
.style("fill", 'rgb(255,255,255, 0.2)')
}

function removeWireframe3(event,d){
svg.selectAll('polyline.wireframe3').remove()
}

//Wireframe Four
//Third interaction from rhino, drone flight route

//edit to add more zones and wireframes, just make sure you channge the parameters
//for drawing the zone that you need to hover over to draw the wireframe
p.enter().append("polyline")
.data(zone4) //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("none", 'white')
.style('fill-opacity','0')
.style("stroke-width", '0.2')
.style("stroke", 'white')
.style("fill", 'white')
//.style('stroke-dasharray', '5 5')
.on("mouseover",addWireframe5)
.on("mouseout",removeWireframe5)
function addWireframe5(event,d){

p.enter().append("polyline")
.data(wireframe5) //get data to define path
.enter()
.append('polyline')
.attr('class', 'wireframe5')
.attr("points", function(d) {return d}) //The d attribute defines a path to be drawn, only applies to appended elements
.style("none", 'rgb(120, 210, 187, 0.7)')
.style('fill-opacity','1')
.style("stroke-width", '1')
.style("stroke", 'rgb(191, 191, 255, 0.3)')
.style("fill", 'rgb(191, 191, 255, 0.7)')
.style('stroke-dasharray', '2 2')
}

function removeWireframe5(event,d){
svg.selectAll('polyline.wireframe5').remove()
}



//points from google spreadsheet, location tags
/* c.enter().append('circle')
.data(drawparks) //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]+4})
.attr("cy",function(d) {return projection([d.Long,d.Lat])[1]+10})
.attr('r',4)
.attr('fill', 'rgb(72,209,204)')
.style('fill-opacity','0.4')
.style("stroke-width", "3")
.style("stroke", "white")
.on("mouseover",addText)
.on("mouseout",removeText)


/*/




//Display names from Spreadsheets
t.enter().append('text')
.data(drawparks) //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',100)
.attr("y", function(d,i){return 90+(i*8)})
.attr('fill', 'rgb(255,255,255, 0.2)')
.style('font-family','Cursive')
.style('font-style','italic')
.style("font-size", "6.5px")
.style("text-anchor", "start")
.text(function(d){return d.Name})
.on("mouseover",musText)
.on("mouseout",removemusText)

function removemusText(event,d){
svg.selectAll('line.parkline').remove()
svg.selectAll('polyline.fanicon').style('fill','rgb(152,251,152, 0.3)')
svg.selectAll('polyline.class1').style('fill','rgb(44, 44, 44)')
}


function musText(event,d){
svg.selectAll('polyline.fanicon').style('fill','rgb(156, 123, 134, 1)')
svg.selectAll('polyline.class1').style('fill','rgb(0,0,0, 0.5)')

//These are Lines for annotation
l.enter().append('line')
.data(drawparks) //get data to define path
.enter() //there are more data than elements, this selects them
.append("line") //appends path to data
.attr('class','parkline')
.attr('x1',200)
.attr("y1", function(d,i){return 100+(i*10)})
.attr('x2',function(d) {return projection([d.Long,d.Lat])[0]+4})
.attr("y2",function(d,i){return 100+(i*10)})
.attr('stroke', 'rgb(255,255,255, 0.7)')
.attr('stroke-width', '0.40')
.style('stroke-dasharray', '2 2')



l.enter().append('line')
.data(drawparks) //get data to define path
.enter() //there are more data than elements, this selects them
.append("line") //appends path to data
.attr('class','parkline')
.attr('x1',function(d) {return projection([d.Long,d.Lat])[0]+4})
.attr("y1", function(d,i){return 100+(i*10)})
.attr('x2',function(d) {return projection([d.Long,d.Lat])[0]+4})
.attr("y2",function(d) {return projection([d.Long,d.Lat])[1]+10})
.attr('stroke', 'rgb(255,255,255, 0.7)')
.attr('stroke-width', '0.40')
.style('stroke-dasharray', '2 2')

}




//theater names from QGIS- Use this for points from QGIS
/* t.enter().append('text')
.data(theaters.features) //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',function(d) {return path.centroid(d)[0]})
.attr("y",function(d) {return path.centroid(d)[1]})
.attr('fill', 'white')
.style('font-family','century gothic')
.style('font-style','italic')
.style("font-size", "11.5px")
.text(function(d){return d.properties.Name})
/*/













// for editing the text of the locations
function addText(event,d){
svg //draw text
.append("text") //appends path to data
.attr('class','parkText')
.attr('x',projection([d.Long,d.Lat])[0]+12)
.attr("y",projection([d.Long,d.Lat])[1]-2)
.attr('fill', 'white')
.style('font-family','century gothic')
.style("font-size", "20px")
.style("font-weight", "bold")
.text(d.Name)
var wrap = svg.selectAll("text.parkText")
.each(function(d, i) { wrap_text(d3.select(this), 500) });
svg //draw description
.append("text") //appends path to data
.attr('class','parkText')
.attr('x',700)
.attr("y",350)
.attr('fill', 'white')
.style('font-family','century gothic')
.style('font-style','italic')
.style("font-size", "11.5px")
.text(d.Description)
var wrap = svg.selectAll("text.parkText")
.each(function(d, i) { wrap_text(d3.select(this), 200) });
}
function removeText(){
svg.selectAll('text.parkText').remove()
}



return svg.node();
}
Insert cell
cornertext = FileAttachment("cornertext@1.txt").tsv({array:true})
Insert cell
fan2 = FileAttachment("fan2.txt").tsv({array:true})
Insert cell
wireframe5 = FileAttachment("wireframe5@1.txt").tsv({array:true})
Insert cell
zone4 = FileAttachment("zone4@2.txt").tsv({array:true})
Insert cell
wireframe4 = FileAttachment("wireframe4@2.txt").tsv({array:true})
Insert cell
'https://fonts.adobe.com/'
Insert cell
wireframe3 = FileAttachment("wireframe3@10.txt").tsv({array:true})
Insert cell
zone3 = FileAttachment("zone3@3.txt").tsv({array:true})
Insert cell
watershade3 = FileAttachment("watershade3.txt").tsv({array:true})
Insert cell
waterboundary = FileAttachment("waterboundary.txt").tsv({array:true})
Insert cell
wireframe2 = FileAttachment("wireframe2@4.txt").tsv({array:true})
Insert cell
zone2 = FileAttachment("zone2@5.txt").tsv({array:true})
Insert cell
wireframe1 = FileAttachment("wireframe1@14.txt").tsv({array:true})
Insert cell
zone1 = FileAttachment("zone1@6.txt").tsv({array:true})
Insert cell
fan1 = FileAttachment("fan1@6.txt").tsv({array:true})
Insert cell
Insert cell
drawmuseums = d3.csv(museumlink,d3.autoType)
Insert cell
theaters = FileAttachment("theaters.geojson").json()
Insert cell
Insert cell
drawparks = d3.csv(parklink,d3.autoType)
Insert cell
Insert cell
mainFlyingPoints = FileAttachment("main flying points.txt").tsv({array:true})
Insert cell
backdropCircle = FileAttachment("backdrop Circle@6.txt").tsv({array:true})
Insert cell
background1 = FileAttachment("background1@2.txt").tsv({array:true})
Insert cell
shade2 = FileAttachment("shade2@2.txt").tsv({array:true})
Insert cell
shade1 = FileAttachment("shade1@2.txt").tsv({array:true})
Insert cell
waterbody = FileAttachment("waterbody@3.txt").tsv({array:true})
Insert cell
rangeOfFlight = FileAttachment("range of flight@1.txt").tsv({array:true})
Insert cell
dronePath05 = FileAttachment("Drone Path 05.txt").tsv({array:true})
Insert cell
dronePath04 = FileAttachment("Drone Path 04.txt").tsv({array:true})
Insert cell
dronePathLoop = FileAttachment("Drone Path Loop.txt").tsv({array:true})
Insert cell
dronePath03 = FileAttachment("Drone Path 03.txt").tsv({array:true})
Insert cell
dronePath02 = FileAttachment("Drone Path 02.txt").tsv({array:true})
Insert cell
smallerFlyingZone = FileAttachment("Smaller flying Zone@1.txt").tsv({array:true})
Insert cell
dronelogo2 = FileAttachment("dronelogo@4.txt").tsv({array:true})
Insert cell
basemap01 = FileAttachment("BaseMap01.geojson").json()
Insert cell
vortex = FileAttachment("Vortex@1.txt").tsv({array:true})
Insert cell
waterfront = FileAttachment("waterfront.geojson").json()
Insert cell
cbox = FileAttachment("Cbox@2.geojson").json()
Insert cell
mouth = FileAttachment("mouth.txt").tsv({array:true})
Insert cell
eyes = FileAttachment("eyes.txt").tsv({array:true})
Insert cell
face_outline = FileAttachment("face_outline.txt").tsv({array:true})
Insert cell
bbox_new = FileAttachment("bbox_new.geojson").json()
Insert cell
graphic_test = FileAttachment("graphic_test.txt").tsv({array:true})
Insert cell
bbox1 = FileAttachment("bbox@1.geojson").json()
Insert cell
restrooms = FileAttachment("restrooms.geojson").json()
Insert cell
subways = FileAttachment("subways.geojson").json()
Insert cell
parks = FileAttachment("parks.geojson").json()
Insert cell
dining_lines = FileAttachment("dining_lines.geojson").json()
Insert cell
Insert cell
spots = d3.csv(spotsLink,d3.autoType)
Insert cell
background = FileAttachment("background@1.txt").tsv({array:true})
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