Public
Edited
Apr 9, 2023
Insert cell
Insert cell
choropleth = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);
// As mentioned early, we created the area on which the map will be created on. The svg is the area we will be creating a map in
svg.append("g")
.attr("transform", "translate(360,20)") // Controls the position of the legend (x, y) x-left and right, y-up and down
.append(() =>
legend({
color: color, // Sets the colors on the legend from our color object earlier
title: data.title, // Sets the title of the legend using the data object we created earlier
width: 350, // Controls the width of the legend
tickFormat: ".1f" // Controls the decimal place of the numbers used on the legend (ie. 3.1 versus 3.112)
})
);
// This function creates the legend graphics , or ("g"), while the functions within control aspects of the legend
svg.append("g")
.selectAll("path")
.data(counties.features)
.join("path")
.attr("stroke", "white")
.attr("stroke-linejoin", "round")
.attr("stroke-width", 1)
// The .attr above control the graphics of how the separation of counties look. For example if I changed "white" to "black" the lines separating the counties would become black and if I changed the "stroke-width" to 2 instead of 1 the lines separating each county would become thicker.
//.attr("fill", function(d){
// console.log(color(data.get(d.properties.GeoID)))
// return color(data.get(d.properties.GeoID));
// })
.attr("fill", d => color(data.get(d.properties.GEOID20)))
.attr("d", path)
.append("title")
.text(d => " Median Age: " + data.get(d.properties.GEOID20));
// The "fill" attribute will assign the colors to each county according the the AreaID. The counties are identified from the AreaID and the percentage associated with that county. The .append function will then assign a title to each county based upon the text you enter in the .text line of code. So when you hover your mouse over a county it will display the given title from your text. It will also display the value from the line of code after the "+". So it will look like this - "Median Age: 40.0" or whatever you are trying to map.
return svg.node();
}
Insert cell
//Before starting you will need to join your .shp .dbf .prj and .shx files into a Topojson file using mapshaper. Also, if your data doesn't have a csv you can also use mapshaper to convert it to a csv file. You will need a Topojson and csv file for this assignment.
Insert cell
d3 = require("d3@5")
Insert cell
import {legend} from "@d3/color-legend"
Insert cell
simple = require("simple-statistics@7.0.7/dist/simple-statistics.min.js")
Insert cell
format = d => `${d}%`
Insert cell
topojson = require("topojson-client@3")
Insert cell
Washington = FileAttachment("Countyq84.json").json()
Insert cell
counties = topojson.feature(Washington, Washington.objects.Countyq84)
Insert cell
csv_data = d3.csvParse(await FileAttachment("CensusData@2.csv").text(),({GEOID20, Total2022}) => [GEOID20, [+Total2022]])
Insert cell
data = Object.assign(new Map(csv_data), {title: "Median Age"})
Insert cell
median_age = Array.from(csv_data.values(), d => d[1][0])

Insert cell
WtLbBl = [d3.color("#eff3ff"), d3.color("#bdd7e7"), d3.color("#6baed6"), d3.color("#2171b5"), d3.color("#08519c")]
// This creates a function using five different HEX codes from color brewer. This function stores the color info in an array to be called on later when filling in the counties on the map. Information such as brightness, rgb, and many more about each color.
Insert cell
Equalinterval = [d3.min(median_age),d3.max(median_age)]
// This function takes the minimum value and the maximum value of our array containing the calculated values that we want to map. If doing an Equal interval chloropleth map you would then use this function inside the color function below within the .domain
Insert cell
//more information on sequential scales: https://observablehq.com/@d3/sequential-scales
// color = d3.scaleSequentialQuantile([...data.values()], d3.interpolateBlues)

// color = d3.scaleQuantile()
// .domain(med_age)
// .range()

color = d3.scaleQuantize()
.domain(Equalinterval)
.range(WtLbBl)
// This function will use the array with colors to join them with the values we are mapping to their appropriate tiers/colors
Insert cell
width = 975
// This will modify the width of our entire map below by regulating the area it will be mapped on through it's width
Insert cell
height = 600
// This will also modify our entire map below by regulating the height of the area it will be mapped on
Insert cell
margin = 100
Insert cell
//Rotate the map sets the longitude of origin for our UTM Zone 15N projection.
//projection = d3.geoTransverseMercator().rotate([94,0]).fitExtent([[80, 80], [width, height]], counties);
//projection = d3.geoConicConformal()
// .parallels([47 + 30 / 60, 48 + 44 / 60])
// .rotate([120 + 50 / 60, 0])
// .fitExtent([[80, 80], [width, height]], counties);
//projection = d3.geoTransverseMercator()
// .rotate([110 + 5 / 60, -40 - 30 / 60]);
//d3 reference for projections: https://github.com/d3/d3-geo/blob/master/README.md

//use the following url for specific projection settings: https://github.com/veltman/d3-stateplane
//Use this code to set up the map projection (if different than geographic projection)
//projection = d3.geoAlbersUsa().scale(1300).translate([487.5, 305])
//projection = d3.geoAlbersUsa().fitExtent([[margin, margin], [width - margin, height - margin]], counties)

projection = d3.geoMercator().fitExtent([[margin, margin], [width - margin, height - margin]], counties)
Insert cell
// The code above is determinant on the area you are trying to map. For example, this is a map of Washington so I used the State of Washington's projection code seen above. Using the link above you can navigate to a multitude of projections
Insert cell
//Using a path generator to project geometry onto the map
path = d3.geoPath().projection(projection);
// This code will remain the same no matter the change in projection
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