Public
Edited
May 24, 2023
6 forks
1 star
Insert cell
Insert cell
//type = [food,bar,store,coffee]
Insert cell
Insert cell
spots = d3.csv(spotsLink,d3.autoType)
Insert cell
walks = FileAttachment("walks@1.geojson").json()
Insert cell
curbs = FileAttachment("curbs.geojson").json()
Insert cell
walks1 = FileAttachment("weekend_walk.geojson").json()
Insert cell
{const people = [{movie:'movie1',color:'red'},{movie:'movie2',color:'red2'}]

return people
}
Insert cell
zips = FileAttachment("boundaries.geojson").json()
Insert cell
nycParks = FileAttachment("parks_nyc_reduced@2.geojson").json()
Insert cell
subway_lines = FileAttachment("subway_lines@2.geojson").json()
Insert cell
subSts = FileAttachment("subway_sts@1.geojson").json()
Insert cell
bbox = FileAttachment("site_boundaries.geojson").json()
Insert cell
d3 = require("d3@6")
Insert cell
box = 'https://docs.google.com/spreadsheets/d/e/2PACX-1vRlLW6JcSye2uCpq29RZVWNXSCgTKcrPtQZ7XCqGOJuwzf0ZVUB3rhz3x1L2TVgBdRlVo8IZHjylk_Y/pub?output=csv'
Insert cell
studioSite = d3.csv(box,d3.autoType)
Insert cell
Insert cell
pois = d3.csv(poiLink,d3.autoType)
Insert cell
bldgs = FileAttachment("bldgs.geojson").json()
Insert cell
chart = {
const width = 960,
height = 900;
const svg = d3.create("svg")
.attr("viewBox", [-60, 60, width, height]);

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

var path = d3.geoPath().projection(projection);
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 g = svg.append("g").attr("id", "paths");

g.selectAll("path") //d3 geopath
//svg
//.selectAll('path')
.data(bldgs.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('stroke-opacity','.2')
.style("stroke-width", '.5')
.style("stroke", "rgb(0,0,0)")

g.selectAll("path5") //d3 geopath
//svg
//.selectAll('path')
.data(curbs.features) //get data to define path
.enter() //there are more data than elements, this selects them
.append("path") //appends path to data
.attr('class','curbs')
.attr("d", path) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "none")
.style('stroke-opacity','.5')
.style("stroke-width", '.5')
.style("stroke", "rgb(0,0,0)")

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", "white")
.style('fill-opacity','.5')
.style("stroke-width", '.5')
.style("stroke", "rgb(0,0,0)")


g.selectAll("path") //d3 geopath
.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','.25')
.style("stroke-width", ".1")
.style("stroke", "rgb(0,255,0)")


var cir = svg.selectAll("circle") //d3 geopath
.data(spots) //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]})
.attr("cy",function(d) {return projection([d.long,d.lat])[1]})
.attr('r', spotSize)
.attr('fill', 'black')
.style('fill-opacity','1')
.style("stroke-width", "1")
.on('mouseover', spotText)
.on('mouseleave', spotErase)

function spotSize(d,i){
var r = 2
if(d.type=='bldg'){r=1.5}
return r
}

function spotText(event,d){
d3.select(this).style("fill", 'cyan');

svg
.append('text')
.attr('class','spotText')
.attr('x','370')
.attr('y','385')
.attr("font-family", "Helvetica")
.attr('font-size','.75em')
.attr('font-weight','bold')
.attr('fill','rgb(0,0,0)')
.attr('text-anchor','end')
//.attr('background-color', 'rgba(255, 0, 0)')
.text(d.name)

svg
.append('text')
.attr('class','spotText')
.attr('x','370')
.attr('y','400')
.attr("font-family", "Helvetica")
.attr('font-size','.75em')
.attr('fill','rgb(0,0,0)')
.attr('text-anchor','end')
//.attr('background-color', 'rgba(255, 0, 0)')
.text(d.description)

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

function spotErase(event,d){
d3.selectAll('circle.spots').style('fill','black')
d3.selectAll('text.spotText').remove()
}

svg.append("circle") //d3 geopath
.attr('class','home')
.attr('cx',function(d) {return projection([-73.99431354,40.69009372])[0]})
.attr("cy",function(d) {return projection([-73.99431354,40.69009372])[1]})
.attr('r', '3')
.attr('fill', 'cyan')
.style('fill-opacity','1')
.style("stroke-width", ".5")
.style('stroke','black')
.style('transform','translate(100 100)')
.on('mouseover', homeText)
.on('mouseleave', homeErase)

function homeText(event,d){
d3.select(this).style("fill", 'black');

svg
.append('text')
.attr('class','homeText')
.attr('x','370')
.attr('y','385')
.attr("font-family", "Helvetica")
.attr('font-size','.75em')
.attr('font-weight','bold')
.attr('fill','rgb(0,0,0)')
.attr('text-anchor','end')
//.attr('background-color', 'rgba(255, 0, 0)')
.text('home sweet home')


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

function homeErase(event,d){
d3.selectAll('circle.home').style('fill','cyan')
d3.selectAll('text.homeText').remove()
}

svg
.append('text')
.attr('class','streets')
.attr('x','650')
.attr('y','620')
.attr("font-family", "Helvetica")
.attr('font-size','.45em')
.attr('font-weight','600')
.attr('fill','rgb(0,0,0)')
.attr('text-anchor','end')
.text('Clinton St.')

svg
.append('text')
.attr('class','streets')
.attr('x','600')
.attr('y','600')
.attr("font-family", "Helvetica")
.attr('font-size','.45em')
.attr('font-weight','600')
.attr('fill','rgb(0,0,0)')
.attr('text-anchor','end')
.text('Henry St.')
/*
//display site circle location
var cir = svg.append("g").attr("id", "paths");
cir = svg.selectAll("circle") //d3 geopath
.data(studioSite) //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', '8')
.attr('fill', 'black')
.style('fill-opacity','1')
.style("stroke-width", "1")
*/
//display site name
var t = svg.selectAll('text')
/*
t.enter().append('text')
.data(studioSite)
.enter()
.append('text')
.attr('class','annotation')
.attr('x','370')
.attr('y','385')
.attr("font-family", "Helvetica")
.attr('font-size','1em')
.attr('fill','rgb(0,0,0)')
.attr('text-anchor','end')
//.attr('background-color', 'rgba(255, 0, 0)')
.text(function(d){return d.name})

//display site description
//var t = svg.selectAll('text')
t.enter().append('text')
.data(studioSite)
.enter()
.append('text')
.attr('class','siteDescription')
.attr('x','370')
.attr('y','400')
.attr("font-family", "Helvetica")
.attr('font-size','.5em')
.attr('fill','rgb(0,0,0)')
.attr('text-anchor','end')
.text(function(d){return d.description})
*/
//use word wrap function to limit line width
var wrap = svg.selectAll("text.siteDescription")
.each(function(d, i) { wrap_text(d3.select(this), 200) });
/*
//add line from site point
var ln = svg.append("g").attr("id", "paths");
ln = svg.selectAll("line")
.data(studioSite) //get data to define path
.enter()
.append('line')
.attr('class','site')
.attr('x1','403')
.attr('y1','380')
.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)')

//add line from pixel location to another pixel location
svg
.append('line')
.attr('class','site')
.attr('x1',373)
.attr('y1',380)
.attr('x2',403)
.attr('y2',380)
.attr('stroke-width','.8')
.attr('stroke-opacity','1')
.style('stroke','rgb(0,0,0)')





//studio poi locations
var cir2 = svg.append("g").attr("id", "paths");
cir2 = svg.selectAll("circle") //d3 geopath
.data(pois) //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', 'black')
.style('fill-opacity','1')
.style("stroke-width", "1")
.on('mouseover', poiText)
.on('mouseout', poiErase)


t.enter().append('text')
.data(pois)
.enter()
.append('text')
.attr('class','poisd')
.attr('x','130')
.attr('y',function(d, i) { return i * 60 + 330; })
.attr("font-family", "Helvetica")
.attr('font-size','.7em')
.attr('text-anchor','end')
.style("font-weight","bold")
.text(function(d){return d.name})

t.enter().append('text')
.data(pois)
.enter()
.append('text')
.attr('class','poisd')
.attr('x','130')
.attr('y',function(d, i) { return i * 60 + 340; })
.attr("font-family", "Helvetica")
.attr('font-size','.7em')
.attr('text-anchor','end')
//.style("font-weight","bold")
.text(function(d){return d.description})

var ln = svg.selectAll('line')
ln.enter().append('line')
.data(pois)
.enter()
.append('line')
.attr('class','poisl')
.attr('x1','135')
.attr('y1',function(d, i) { return i * 60 + 325; })
.attr('x2',165)
.attr('y2',function(d, i) { return i * 60 + 325; })
.attr('stroke-width','.8')
.attr('stroke-opacity','1')
.attr('stroke-dasharray',"4 4")
.style('stroke','rgb(100,100,100)')

ln.enter().append('line')
.data(pois)
.enter()
.append('line')
.attr('class','poisl')
.attr('x1','165')
.attr('y1',function(d, i) { return i * 60 + 325; })
.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')
.attr('stroke-dasharray',"4 4")
.style('stroke','rgb(100,100,100)')

//mouseover function for poi text
function poiText(event,d){

//poi names
svg
.append("text") //appends path to data
.attr('class','pois')
.attr('x','370')
.attr('y','570')
.attr("font-family", "Helvetica")
.attr('font-size','.8em')
.attr('text-anchor','end')
//.style("font-weight","bold")
.text(d.name)

//poi descriptions
svg
.append("text") //appends path to data
.attr('class','pois')
.attr('x','370')
.attr('y','580')
.attr("font-family", "Helvetica")
.attr('font-size','.5em')
.attr('text-anchor','end')
//.style("font-weight","bold")
.text(d.description)

//add line from pixel location to another pixel location
svg
.append('line')
.attr('class','pois')
.attr('x1',373)
.attr('y1',565)
.attr('x2',403)
.attr('y2',565)
.attr('stroke-width','.8')
.attr('stroke-opacity','1')
.style('stroke','rgb(0,0,0)')


svg.append('line')
.attr('class','pois')
.attr('x1','403')
.attr('y1','565')
.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)')

//use word wrap function to limit line width
var wrap = svg.selectAll("text.pois")
.each(function(d, i) { wrap_text(d3.select(this), 200) });
}
*/
var wrap = svg.selectAll("text.poisd")
.each(function(d, i) { wrap_text(d3.select(this), 160) });

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


g.selectAll("path2") //d3 geopath
//svg
//.selectAll('path')
.data(subway_lines.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-opacity','0')
.style("stroke-width", ".15")
.style("stroke", "rgb(0,0,0)")

g.selectAll("circle") //d3 geopath
//svg
//.selectAll('path')
.data(subSts.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',1.5)
.attr('fill','black')
.style('fill-opacity','.9')

//var t = svg.selectAll('text')
t.enter().append('text')
.data(subSts.features)
.enter()
.append('text')
.attr('class','subStops')
.attr('x',function(d) {return path.centroid(d)[0]})
.attr('y',function(d) {return path.centroid(d)[1]-5})
.attr("font-family", "Helvetica")
.attr('font-size','.55em')
.attr('fill','rgb(0,0,0)')
.attr('text-anchor','middle')
.text(function(d){return d.properties.name})
g.selectAll("path4") //d3 geopath
.data(walks.features) //get data to define path
.enter() //there are more data than elements, this selects them
.append("path") //appends path to data
.attr('class','walks')
.attr("d", path4) //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-dasharray", "4 2")
.style("stroke", "rgb(0,0,0)")
.on('mouseover', walkText)
.on('mouseleave', walkErase)

function walkText(event,d){
d3.select(this).style("stroke-width", '3');
d3.select(this).style("stroke-dasharray", '4 0');

svg
.append('text')
.attr('class','walkText')
.attr('x','370')
.attr('y','385')
.attr("font-family", "Helvetica")
.attr('font-size','.75em')
.attr('fill','rgb(0,0,0)')
.attr('text-anchor','end')
//.attr('background-color', 'rgba(255, 0, 0)')
.text(d.properties.Text)

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

function walkErase(event,d){
d3.selectAll('path.walks').style('stroke-width','1')
d3.selectAll('path.walks').style('stroke-dasharray','4 2')
d3.selectAll('text.walkText').remove()
}



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