Published
Edited
Mar 2, 2022
Fork of starter map
Insert cell
# starter map
Insert cell
//zips = FileAttachment("zip_test4.geojson").json()
Insert cell
grocerysites = d3.csv(box,d3.autoType)
Insert cell
//roads = FileAttachment("Roads-Small4@1.geojson").json()
Insert cell
residence = FileAttachment("residential2.geojson").json()
Insert cell
hydrant = FileAttachment("Fire-Hydrants.geojson").json()

Insert cell
Insert cell
park = FileAttachment("Parks.geojson").json()
Insert cell
busstop = FileAttachment("busstopjson.geojson").json()

Insert cell
d3 = require("d3@6")
Insert cell
data_join = FileAttachment("join_test.geojson").json()
Insert cell
box = "https://docs.google.com/spreadsheets/d/e/2PACX-1vQfDlg4k_bWxkxjcaMrk5VrEQ6mK9QVX8qWcAvbuX8emkw7AN02FXRZlS3f59nW_upzU9nwz_ol0sso/pub?output=csv"

Insert cell
chart = {
const width = 960,
height = 900;
const svg = d3.create("svg")
.attr("viewBox", [-20, 140, width, height]);

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




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 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.append("g").attr("id", "paths");
g.selectAll("path7") //d3 geopath
//svg
//.selectAll('path')
.data(water.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")
//.attr("fill",'rgb(0,0,0)')
// .attr("fill", d => color(d.properties.POPULATION))
// .attr("fill", d => color("black"))
.style('fill-opacity','1')
.style("stroke", "black")
/*
var g = svg.append("g").attr("id", "paths");
g.selectAll("path") //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", "none")
//.attr("fill", d => color(d.properties.POPULATION))
// .attr("fill", d => color(d.properties.POPULATION))
.style('fill-opacity','1')
.style("stroke", "#ccc")
*/

var g = svg.append("g").attr("id", "paths");
g.selectAll("path3") //d3 geopath
//svg
//.selectAll('path')
.data(data_join.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")
//.attr("fill", d => color(d.properties.POPULATION))
.attr("fill", 'none')
.style('fill-opacity','.1')
.style("stroke", "none")

//var g = svg.append("g").attr("id", "paths");

/*
g.selectAll("path4") //d3 geopath
//svg
//.selectAll('path')
.data(roads.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")
//.attr("fill", d => color(d.properties.POPULATION))
.attr("fill", 'none')
.style('fill-opacity','.1')
.style("stroke", "black")
.style("stroke-width", "2.5")
*/

var g = svg.append("g").attr("id", "paths");

var c = svg.selectAll("fills")
// c.enter().append("fills") = svg.selectAll("fills")
g.selectAll("path5") //d3 geopath
//svg
//.selectAll('path')
.data(residence.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", path5) //The d attribute defines a path to be drawn, only applies to appended elements
//.style("fill", "none")
.attr("fill", d => color(d.properties.total))
// .attr("fill",'rgb(0,150,150')
// .style("fill", 'rgb(0,150,150')
//hey megumi, use a static color here for the fill. the above fill is trying to find a populations attribute in your residence feature, which doesn't exist. so you can say 'fill','rgb(255,0,0)', or whatever, but don't try to reference data using the d.whatever method
.attr('fill-opacity','1')
.style("stroke", "black")
.style("stroke-width", ".15")
.on('mouseover', addFill)
.on('mouseleave', removeFill)


//QUESTION FOR FLEET: The color change with mouseover works, but the color doesn't go back to the original like it's supposed to. Remove mouseleave isn't properly functioning. Could you help us out?

//working! also note the fill-opacity, 1 is full color, 0 is transparent
// thanks Fleet!, how do I make the circles smaller for the fire hydrants?
//good q. right now they're paths - which means lines, I'm going to switch them to circle data types, like the subway stop example below
// Okay thanks

//circles should be good, you can change the radius, r, or fill color. We want these maps to pop up as quickly as possible so work on reducing these files coming out of qgis when you have a moment
// okay will do, thank you very much! i'm trying to get the water to show up, but it's not, im gonna update the file real quick ok it worked but it's over stuff, can I change draw orders? //yes, you can change the opacity, or move that block above other items, move the whole chunk of code
// so if i want it to be last, i move it to the end?//i just moved it to be the top/first piece of data, and it's at the bottom, observable draws the top things first and then lower things on top of the previous...
// okay i see, thank you! :D // no prob :)

/*
//var g = svg.append("g").attr("id", "paths");
g.selectAll("circle") //d3 geopath
//svg
//.selectAll('path')
.data(hydrant.features) //get data to define path
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
//.attr('class','outlines')
.attr('cx',function(d){return path.centroid(d)[0]})
.attr('cy',function(d){return path.centroid(d)[1]})
.attr("r", 1.)
.attr("fill", "black")
.attr("fill-opacity", ".5")

*/


var g = svg.append("g").attr("id", "paths");
g.selectAll("path8") //d3 geopath
//svg
//.selectAll('path')
.data(park.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")
//.attr("fill", d => color(d.properties.POPULATION))
.attr("fill", 'none')
.style('fill-opacity','.1')
.style("stroke", "black")
.style("stroke-width", ".4")

var g = svg.append("g").attr("id", "paths");
g.selectAll("circle") //d3 geopath
//svg
//.selectAll('path')
.data(busstop.features) //get data to define path
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
//.attr('class','outlines')
.attr('cx',function(d){return path.centroid(d)[0]})
.attr('cy',function(d){return path.centroid(d)[1]})
.attr("r", 1.5)
.attr("fill", "blue")


/*
g.selectAll("circle") //d3 geopath
//svg
//.selectAll('path')
.data(zips.features) //get data to define path
.enter() //there are more data than elements, this selects them
.append("circle") //appends path to data
//.attr('class','outlines')
//.attr("d", path) //The d attribute defines a path to be drawn, only applies to appended elements
.attr('cx',function(d){return path.centroid(d)[0]})
.attr('cy',function(d){return path.centroid(d)[1]})
//.attr('r',5)
//.attr('r', (d) => d.POPULATION/100)
.attr('r',function(d){return d.properties.POPULATION/10000})
.style("fill", "none")
.style('fill-opacity','.5')
.style("stroke", "#ccc")
*/

var tooltip = svg.append("g");
function addFill(event,d)
{
var a = svg.append('text')
.attr('class','residence')
.attr('x','650')
.attr('y','200')
.attr("font-family", "Helvetica")
.attr('font-size','1em')
.attr('fill','rgb(0,0,0)')
//.attr('text-anchor','end')
.text(d.properties.total + " residents")

var centroid = path.centroid(d);
/*
d3.select(this).attr('fill-opacity', '.9')
// .attr("fill",'rgb(0,150,150')
svg
// .append('text')
// .attr('x','400')
// .attr('y','100')
// .attr('font-size','3em')
// .text(d.properties.total)
tooltip.call(
callout,
`${'Residents:'} ${d.properties.total}`
);
tooltip.attr("transform", "translate(" + centroid + ")");
*/
}


function removeFill(event,d)
{ tooltip.call(callout, null)
d3.select(this).attr("fill", d => color(d.properties.total))
d3.select(this).attr('fill-opacity', '1')
d3.selectAll("text.residence").remove()

}
/*//heyyy you need to change back to .6 opacity inside the same {} - that marks the opening and closing of the function... so within the removefill function you both make the rollover box null, and change the opacity back. make sense? i think it's working now right? - Yeah works how we wanted it to, Thanks! np looking good!
{
// d3.select(this).style("fill", d => color(d.properties.total))
// d3.selectAll('text.labels')
//d3.select(this).attr('fill-opacity', '.6')
//QUESTION FOR FLEET: Mouse leave isn't resetting the opacity back to the starting opacity of .6
.on("mouseleave",function(event, d){tooltip.call(callout, null)})
}
*/

//DISPLAY SITE DOT
//var cir = svg.append("g").attr("id", "paths");
//cir.enter().append("circle")
var cir = svg.selectAll("circle") //d3 geopath
.data(grocerysites) //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', 6)
.attr('fill', 'red')
.style('fill-opacity','.9')
.style("stroke-width", "1")
/*
//DISPLAY SITE DESCRIPTION
var t = svg.selectAll('text')
t.enter().append('text')
.data(grocerysites)
.enter()
.append('text')
.attr('class','annotation')
.attr('x','200')
.attr('y','600')
.attr("font-family", "Helvetica")
.attr('font-size','.5em')
.attr('fill','rgb(0,0,0)')
.attr('text-anchor','end')
.text(function(d){return d.DESCRIPTION})

//DISPLAY SITE NAME
var t = svg.selectAll('text')
t.enter().append('text')
.data(grocerysites)
.enter()
.append('text')
.attr('class','annotation')
.attr('x','200')
.attr('y','600')
.attr("font-family", "Helvetica")
.attr('font-size','.8em')
.attr('fill','rgb(0,0,0)')
.attr('text-anchor','end')
.text(function(d){return d.NAME})

*/
return svg.node();
}
Insert cell
color = d3.scaleQuantize([1, 1100], d3.schemeGreens[9])
Insert cell
import {legend} from "@d3/color-legend"
Insert cell
format = d => `${d}%`
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
path = d3.geoPath()
Insert cell
FileAttachment("Roads-Small.geojson")
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