Published unlisted
Edited
Jul 26, 2022
Fork of base map
Insert cell
# Brooklyn & Queens Textile Drop-off Location
Insert cell
d3 = require("d3@6")
Insert cell
chart = {
const width = 960,
height = 900;
const svg = d3.create("svg")
.attr("viewBox", [50, 50, width-100, height-100]);

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

var path = d3.geoPath().projection(projection);
var path1 = d3.geoPath().projection(projection);
var path2 = d3.geoPath().projection(projection);
var path3 = d3.geoPath().projection(projection);

var g = svg.append("g").attr("id", "paths");
//i'm not using the boundary lines, so I'm going to comment them out
/*
g.selectAll("path1") //d3 geopath
.data(boundary.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", path1) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '.5')
.style("stroke", "rgb(0,0,0)")
*/


g.selectAll("path4") //d3 geopath
.data(communityDistrict.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", path3) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "rgb(240,240,240)")
.style("fill-opacity", ".5")
.style('stroke-opacity','.4')
.style("stroke-width", '.5')
.style("stroke", "rgb(0,0,0)")

g.selectAll("path2") //d3 geopath
.data(subLns.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", path2) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "none")
.style('stroke-opacity','1')
.style("stroke-width", '.10')
.style("stroke", "rgb(0,0,0)")

g.selectAll("path3") //d3 geopath
.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", path3) //The d attribute defines a path to be drawn, only applies to appended elements
.style("fill", "rgb(164,164,164)")
.style("fill-opacity", ".5")
.style('stroke-opacity','0')
.style("stroke-width", '0')
.style("stroke", "rgb(0,0,0)")





var c = svg.selectAll("circle") //d3 geopath
.data(subSts.features)
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr("cx", function(d) {return path1.centroid(d)[0]})
.attr("cy", function(d) {return path1.centroid(d)[1]})
.attr('r',1.5)
.attr('fill','black')
.style('fill-opacity','.25')

/*
c.enter().append('circle')//d3 geopath
.data(textileDropOffLocation.features)
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
.attr("cx", function(d) {return path1.centroid(d)[0]})
.attr("cy", function(d) {return path1.centroid(d)[1]})
.attr('r',2)
.attr('fill','rgb(255,177,158)')
.style('fill-opacity','1')
*/


var g = svg.append("g").attr("id", "paths");
g.selectAll("path") //d3 geopath
//svg
//.selectAll('path')
.data(zips.features) //get data to define path
//console.log(function(d,0){return d})
.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", "#ccc")
.on("mouseover", addBoundingBox)
.on("mouseleave", removeBoundingBox);



var s = svg.append("g").attr("id", "subs");
s.selectAll('path')
.data(textileDropOffLocation.features)
.enter()
.append('path')


var sc = svg.append("g").attr("id", "subsc");
sc.selectAll('circle')
.data(textileDropOffLocation.features)
.enter()
.append('circle')
.attr("cx", function(d) { return path.centroid(d)[0]})
.attr("cy", function(d) { return path.centroid(d)[1]})
.attr('r',4)
.attr('fill','rgb(255,177,158)')
.style('fill-opacity','.75')
.on("mouseover", subTxt)
.on("mouseleave", subTxtOut)

const tooltip2 = svg.append("g");
//.attr("transform", 'scale(1 .5)')
//.attr("r", 1)
//.attr("cx", function(d) { return [0]})
//.attr("cy", function(d) { return [1]})
//console.log(function(d) { return [0]})
/*
svg.append("g").attr("id", "centers");
g.selectAll('circle')
.data(zips.features)
.enter()
.append('circle')
.attr("cx", function(d) { return path.centroid(d)[0]})
.attr("cy", function(d) { return path.centroid(d)[1]})
.attr("r", 2)
.attr("fill", "black")
*/

/*
svg.append("g").attr("id", "words");
g.selectAll("text")
.data(zips.features)
.enter()
.append("text")
.attr("transform", function (d) {
return "translate(" + path.centroid(d) + ")";
})
.attr("font-size", ".15em")
.text(function (d) {
return d.properties.PO_NAME;
});

*/

function addBoundingBox(event, d) {
const centroid = path.centroid(d);
const pat = path(d)

d3.select(this).style("fill", 'red');
//svg
//.append('path')
//.attr('class','hov')
//.attr("id", "hovers")
//.attr("d", pat)
//.style("fill", "gray");
svg
.append("circle")
.attr("class", "centroid")
.attr("cx", 0)
.attr("cy", 0)
.attr("cx", centroid[0])
.attr("cy", centroid[1])

svg
.append("text")
.attr("class", "labels")
.attr('x',100)
.attr('y',100)
.attr("font-size", "2em")
.text(d.properties.PO_NAME);
}
function subTxt(event, d) {

const centroid = path.centroid(d);
d3.select(this).style("fill", 'gray');
svg
.append("text")
//.selectAll("text")
//.data(d.textileDropOffLocation.features)
//.join("text")
//.enter()
.attr("class", "sublabels")
.attr('dx','10px')
.attr('x',centroid[0])
.attr('y',centroid[1])
.attr("font-size", ".55em")
//.text(d.properties.address);
//.text(tooltip(d));
//console.log(tooltip)


//svg
//.selectAll(d)
//tooltip2.call(
//callout,
//`${d.properties.address}
//${d.properties.borough}, ${d.properties.items_acce}`
//);
//tooltip2.attr("transform", "translate(" + centroid + ")");

}
function removeBoundingBox() {

console.log('out')
d3.selectAll("circle.centroid").remove();
d3.selectAll("text.labels").remove();
//d3.selectAll("path.hov").style("fill", 'white');
d3.select(this).style("fill", 'white');
}

function subTxtOut() {

d3.selectAll("text.sublabels").remove();
d3.select(this).style("fill", 'rgb(255,177,158)');
tooltip2.call(callout, null);
}

svg
.selectAll("circle")
.on("touchmove mousemove", function(event, d) {
const centroid = path.centroid(d);
tooltip2.call(
callout,
`${d.properties.address}
${d.properties.ntaname}, ${d.properties.borough}
${d.properties.items_acce}`
);
tooltip2.attr("transform", "translate(" + centroid + ")");
})
//subways()


return svg.node();
}
Insert cell
zips = FileAttachment("zip_test4.geojson").json()
Insert cell
textileDropOffLocation = FileAttachment("Textile Drop Off Location.geojson").json()
Insert cell
subSts = FileAttachment("Subway Station.geojson").json()
Insert cell
bldgs = FileAttachment("House Boundary.geojson").json()
Insert cell
bbox = FileAttachment("Boundary Line.geojson").json()
Insert cell
subLns = FileAttachment("Subway Line.geojson").json()
Insert cell
boundary = FileAttachment("nyc_boundary.geojson").json()
Insert cell
communityDistrict = FileAttachment("Community District.geojson").json()
Insert cell
callout = (g, value) => {
if (!value) return g.style("display", "none");

g
.style("display", null)
.style("pointer-events", "none")
.style("font", "10px sans-serif");

const path = g.selectAll("path")
.data([null])
.join("path")
.attr("fill", "white")
.attr("stroke", "black");

const text = g.selectAll("text")
.data([null])
.join("text")
.call(text => text
.selectAll("tspan")
.data((value + "").split(/\n/))
.join("tspan")
.attr("x", 0)
.attr("y", (d, i) => `${i * 1.1}em`)
.style("font-weight", (_, i) => i ? null : "bold")
.text(d => d));

const {x, y, width: w, height: h} = text.node().getBBox();

text.attr("transform", `translate(${-w / 2},${15 - y})`);
path.attr("d", `M${-w / 2 - 10},5H-5l5,-5l5,5H${w / 2 + 10}v${h + 20}h-${w + 20}z`);
}
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