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

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

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 path9 = 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")
//static lines from QGIS

staticLines(path6, community8.features,"rgb(250,250,250)",'1','1',"gray",'none')
staticLines(path, park8.features,"rgb(204,204,204)",'.25','1',"white",'none')
staticLines(path2, peddemand8.features,"none",'1','.5',"rgb(153,153,153)",'none')
staticLines(path3, publicplazas8.features,"none",'1','1',"rgb(153,153,153)",'none')
staticLines(path4, openspacesOther8.features,"none",'1','1',"rgb(153,153,153)",'none')
staticLines(path5, railroad8.features,"none",'1','.1',"black",'none')

function staticLines(path, data, sfill, sOpac, sW, stroke,dashstyle){

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)
.style('stroke-dasharray',dashstyle)
}


//lines from RHINO

//polyline(network,'none','1','.25','rgb(0,102,153)')
//polyline(connectingroute,'none','1','1','rgb(204,102,102)')
polyline(vortex,'none','.1','3','rgb(255,159,42)','none')
//polyline(boxAddress,'rgb(250,250,250)','1','1.5','black','6 4')
function polyline(data, sfill, sOpac, sW, stroke, dashstyle){

p.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)
.style('stroke-dasharray',dashstyle)
}


//static points from QGIS
//staticCircles(library8.features,'5','rgb(255,102,0)','5',"1")
staticCircles(pops8.features,'3','rgb(0,153,204)','5',"1")
//staticCircles(streetseats8.features,'4','red','5',"1")
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)
}


////////////////////////////-------PART 2-------
//// Adding interactive POP ZONE

p.enter().append("polyline")
.data(zone9Pop) //get data to define path
.enter() //there are more data than elements, this selects them
.append('polyline')
.attr("points", function(d) {return d})
.style("fill", 'white')
.style('fill-opacity','0')
.style("stroke-width", '2')
.style("stroke", 'black')
.style('stroke-dasharray','5 3')
.on("mouseover",activatePOPzone)
.on("mouseout",removePOPzone)

function activatePOPzone(event,d){
svg
g.enter().append("path")
.data(publicplazas8.features)
.enter()
.append("path")
.attr('class','popzone')
.attr("d", path)
.style("fill",'rgb(0,102,153)')
.style('fill-opacity','.25')
.style('stroke-opacity','1')
.style("stroke-width",'.25')
.style("stroke",'black')
p.enter().append("polyline")
.data(textobj9Pop)
.enter()
.append('polyline')
.attr('class','popzone')
.attr("points", function(d) {return d})
.style("fill", 'none')
.style("stroke-width",'1.5')
.style("stroke", 'rgb(0,102,153)')
p.enter().append("polyline")
.data(network)
.enter()
.append('polyline')
.attr('class','popzone')
.attr("points", function (d){return d})
.style("fill",'none')
.style('stroke-opacity','1')
.style("stroke-width",'.25')
.style("stroke", 'rgb(0,102,153)')
}

function removePOPzone(event,d){
svg.selectAll('polyline.popzone').remove()
svg.selectAll('path.popzone').remove()
}


//// Adding ICON (starshape) from spreadsheet locations

p.enter().append("polyline")
.data(library9)
.enter()
.append('polyline')
.attr("points", icon9Lib)
.attr('class','lIcon')
.attr('transform',function(d) {return 'translate('+projection([d.Long,d.Lat])[0]+','+projection([d.Long,d.Lat])[1]+')'})
.style("fill",'orange')
.style("stroke-width",'.5')
.style("stroke",'orange')
.on("mouseover",addLibGraphics)
.on("mouseout",removeLibGraphics)

function addLibGraphics(event,d){
//---highlight OTHER OPEN SPACES
svg
g.enter().append("path")
.data(openspacesOther8.features)
.enter()
.append("path")
.attr('class','otherOpen')
.attr("d", path)
.style("fill",'rgb(153,204,153)')
.style('fill-opacity','.75')
.style('stroke-opacity','.75')
.style("stroke-width",'1')
.style("stroke",'rgb(51,102,51)')
//---ANNOTATION lines
svg.append("line")
.attr('class','annot')
.attr('x1',50)
.attr("y1",39.5)
.attr('x2',50)
.attr("y2",projection([d.Long,d.Lat])[1])
.attr('stroke', 'brown')
.attr('stroke-width', '1.25')
.style('stroke-dasharray','6 4')
svg.append("line")
.attr('class','annot')
.attr('x1',50)
.attr("y1",projection([d.Long,d.Lat])[1])
.attr('x2',projection([d.Long,d.Lat])[0])
.attr("y2",projection([d.Long,d.Lat])[1])
.attr('stroke', 'brown')
.attr('stroke-width', '1.25')
.style('stroke-dasharray','6 4')
//---Pop-up ADDRESS box
p.enter().append("polyline")
.data(boxAddress)
.enter()
.append('polyline')
.attr("points", function (d){return d})
.attr('class','lRhino')
.style("fill",'rgb(255,255,204)')
.style('stroke-opacity','1')
.style("stroke-width",'1.5')
.style("stroke",'rgb(153,51,51)')
.style('stroke-dasharray','6 4')
//---Pop-up VORTEX thread
var libName = d.ID
if(libName==1){drawVorThread(threadLib1)}
if(libName==2){drawVorThread(threadLib2)}
if(libName==3){drawVorThread(threadLib3)}
if(libName==4){drawVorThread(threadLib4)}
if(libName==5){drawVorThread(threadLib5)}
if(libName==6){drawVorThread(threadLib6)}
if(libName==7){drawVorThread(threadLib7)}
if(libName==8){drawVorThread(threadLib8)}
if(libName==9){drawVorThread(threadLib9)}
if(libName==10){drawVorThread(threadLib10)}
if(libName==11){drawVorThread(threadLib11)}
function drawVorThread(data){
p.enter().append("polyline")
.data(data)
.enter()
.append('polyline')
.attr('class','lRhino')
.attr("points", function(d){return d})
.style("fill",'none')
.style('stroke-opacity','.5')
.style("stroke-width",'4')
.style("stroke",'brown')
}
//---highlight ICON's graphics
d3.select(this).style('fill','pink').style('fill-opacity','1').style('stroke-width','2').style('stroke','purple')
//---Pop-up NAMES
svg
.append("text")
.attr('class','lText')
.attr('x',projection([d.Long,d.Lat])[0]+20)
.attr("y",projection([d.Long,d.Lat])[1]-20)
.attr('fill','rgb(153,51,51)')
.style('font-family','bahnschrift')
.style("font-size", "15px")
.text(d.Name)
//---ADDRESS at fixed location
svg
.append("text")
.attr('class','lText')
.attr('x',25)
.attr("y",25)
.attr('fill', 'black')
.style('font-family','bahnschrift')
.style("font-size", "14px")
.text('Address: '+d.Address)
//---rearrange
this.parentElement.appendChild(this)
//---wrap pop-up names
var wrap = svg.selectAll("text.lText")
.each(function(d, i) { wrap_text(d3.select(this), 100) })
}

function removeLibGraphics(){
svg.selectAll('path.otherOpen').remove()
svg.selectAll('text.lText').remove()
svg.selectAll('polyline.lRhino').remove()
svg.selectAll('line.annot').remove()
d3.select(this).style('fill','orange')
.style('stroke-width','.5').style('stroke','orange')
}

//// Display STREET SEATS infos from QGIS

t.enter().append('text')
.data(streetseats8.features) //get data to define path
.enter() //there are more data than elements, this selects them
.append("text") //appends path to data
.attr('class','sText')
.attr('x',function(d) {return path.centroid(d)[0]-10})
.attr("y",function(d) {return path.centroid(d)[1]+25})
.attr('fill', 'gray')
.style('font-family','bahnschrift')
.style('text-anchor','start')
.style("font-size", "6px")
.text(function(d){return d.properties.ifo_busine})
t.enter().append('text')
.data(streetseats8.features) //get data to define path
.enter() //there are more data than elements, this selects them
.append("text") //appends path to data
.attr('class','sText')
.attr('x',function(d) {return path.centroid(d)[0]-10})
.attr("y",function(d) {return path.centroid(d)[1]+32})
.attr('fill', 'gray')
.style('font-family','bahnschrift')
.style('text-anchor','start')
.style("font-size", "6px")
.text(function(d){return d.properties.location})

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


//// Adding SEAT ICON (seat shape) from RHINO

p.enter().append("polyline")
.data(icon9Ss1)
.enter()
.append('polyline')
.attr('class','seat')
.attr("points", function(d) {return d})
.style("fill", 'red')
.style("stroke-width", '1')
.style("stroke", 'red')
.on("mouseover",activateRoute)
.on("mouseout",removeRoute)


function activateRoute(event,d){
svg
p.enter().append("polyline")
.data(connectingroute)
.enter()
.append('polyline')
.attr('class','seatflash')
.attr("points", function(d) {return d})
.style("fill", 'none')
.style("stroke-width",'2')
.style("stroke", 'rgb(204,102,102)')

p.enter().append("polyline")
.data(icon9Ss1)
.enter()
.append('polyline')
.attr('class','seatflash')
.attr("points", function(d) {return d})
.style("fill", 'white')
.style("stroke-width", '1.5')
.style("stroke", 'white')
p.enter().append("polyline")
.data(icon9Ss2)
.enter()
.append('polyline')
.attr('class','seatflash')
.attr("points", function(d) {return d})
.style("fill", 'red')
.style("stroke-width", '.2')
.style("stroke", 'white')

p.enter().append("polyline")
.data(textobj9Ss)
.enter()
.append('polyline')
.attr('class','seatflash')
.attr("points", function(d) {return d})
.style("fill", 'none')
.style("stroke-width",'.75')
.style("stroke", 'rgb(204,102,102)')
}
function removeRoute(event,d){
svg.selectAll('polyline.seatflash').remove()
}


return svg.node();
}
Insert cell
boxAddress = FileAttachment("box-address@2.txt").tsv({array:true})
Insert cell
threadLib1 = FileAttachment("thread-lib-1.txt").tsv({array:true})
Insert cell
threadLib2 = FileAttachment("thread-lib-2.txt").tsv({array:true})
Insert cell
threadLib3 = FileAttachment("thread-lib-3.txt").tsv({array:true})
Insert cell
threadLib4 = FileAttachment("thread-lib-4.txt").tsv({array:true})
Insert cell
threadLib5 = FileAttachment("thread-lib-5.txt").tsv({array:true})
Insert cell
threadLib6 = FileAttachment("thread-lib-6.txt").tsv({array:true})
Insert cell
threadLib7 = FileAttachment("thread-lib-7.txt").tsv({array:true})
Insert cell
threadLib8 = FileAttachment("thread-lib-8.txt").tsv({array:true})
Insert cell
threadLib9 = FileAttachment("thread-lib-9.txt").tsv({array:true})
Insert cell
threadLib10 = FileAttachment("thread-lib-10.txt").tsv({array:true})
Insert cell
threadLib11 = FileAttachment("thread-lib-11.txt").tsv({array:true})
Insert cell
icon9Ss = FileAttachment("icon9-ss@4.txt").tsv({array:true})
Insert cell
icon9Ss1 = FileAttachment("icon9-ss-1@2.txt").tsv({array:true})
Insert cell
icon9Ss2 = FileAttachment("icon9-ss-2@1.txt").tsv({array:true})
Insert cell
textobj9Ss = FileAttachment("textobj9-ss.txt").tsv({array:true})
Insert cell
textobj9Pop = FileAttachment("textobj9-pop@1.txt").tsv({array:true})
Insert cell
zone9Pop = FileAttachment("zone9-pop.txt").tsv({array:true})
Insert cell
icon9Lib = FileAttachment("icon9-lib@3.txt").tsv({array:true})
Insert cell
library9 = d3.csv(library9Link,d3.autoType)
Insert cell
Insert cell
connectingroute = FileAttachment("ConnectingRoute.txt").tsv({array:true})
Insert cell
vortex = FileAttachment("Vortex.txt").tsv({array:true})
Insert cell
network = FileAttachment("Network.txt").tsv({array:true})
Insert cell
park8 = FileAttachment("park-8.geojson").json()
Insert cell
community8 = FileAttachment("Community-8.geojson").json()
Insert cell
railroad8 = FileAttachment("Railroad-8.geojson").json()
Insert cell
openspacesOther8 = FileAttachment("OpenSpaces-other-8.geojson").json()
Insert cell
publicplazas8 = FileAttachment("PublicPlazas-8.geojson").json()
Insert cell
streetseats8 = FileAttachment("StreetSeats-8.geojson").json()
Insert cell
pops8 = FileAttachment("Pops-8.geojson").json()
Insert cell
library8 = FileAttachment("Library-8.geojson").json()
Insert cell
bbox8Qgis = FileAttachment("bbox-8-qgis.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
peddemand8 = FileAttachment("PedDemand-8.geojson").json()
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