I am trying to figure out what went wrong with my code since I have not been able to generate anything else than a big square of a single color while I try to get a colorScale for each element with the class "county" of this Albers US map.
The project should look like this: https://choropleth-map.freecodecamp.rocks/
The weirdest thing is that I validate the test.
I am using d3.js and put it in a React 18 component and I use Babel for rendering through another HTML file.
The snippet which might be blocking:
const createChoroplethMap = (counties, educationData, width, height, margins) => {
// create SVG element
const svg = d3.select("#chomap")
.append("svg")
.attr("width", width + margins.left + margins.right)
.attr("height", height + margins.top + margins.bottom);
// create projection and path generator
const projection = d3.geoAlbersUsa();
const pathGenerator = d3.geoPath().projection(projection);
// create color scale
const colorScale = d3.scaleQuantize()
.domain([0, d3.max(educationData, d => d.bachelorsOrHigher)])
.range(d3.schemeBlues[9]);
// draw counties
svg.selectAll(".county")
.data(topojson.feature(counties, counties.objects.counties).features)
.enter().append("path")
.attr("class", "county")
.attr("d", pathGenerator)
.attr("fill", d => {
const county = educationData.find(e => e.fips === d.id);
console.log(county.bachelorsOrHigher)
return colorScale(county.bachelorsOrHigher);
})
.attr("data-fips", d => d.id)
.attr("data-education", d => {
const county = educationData.find(e => e.fips === d.id);
return county.bachelorsOrHigher;
});
// draw states
svg.selectAll(".state")
.data(topojson.feature(counties, counties.objects.states).features)
.enter().append("path")
.attr("class", "state")
.attr("d", pathGenerator);
};
Link to the project on codepen: https://codepen.io/reggr0y/pen/QWVoBOR
You can fix your codepen in 2 ways:
Based on the freecodecamp script it is implied that this topojson is already projected. So you can simply comment out the projection
call below.
const pathGenerator = d3.geoPath() //.projection(projection);
Perhaps this was called out in the tutorial/ course you are following, and if not, it is common to pre-project for Albers USA maps because it is a constructed map that does not follow real geography (e.g. Alaska and Hawaii are not really where they are).
There is a simpler pre-projected Albers USA in this example for a reference without the choropleth mechanics. Whilst the projection
is given for data overlays, note in the rendering code Mike Bostock does not use the projection
and path
is simply defined as d3.geoPath()
.
Perhaps, it is also worth reading through the problems/ answers here and here from Andrew Reid.
Second, you draw the states over the top of the counties, so make the fill none
and the stroke black
:
// draw states
svg.selectAll(".state")
.data(topojson.feature(counties, counties.objects.states).features)
.enter().append("path")
.attr("class", "state")
.attr("d", pathGenerator)
.attr("fill", "none") // <-- add
.attr("stroke", "black"); // <-- add
Here's the outcome from removing the projection - note you just see the black states because they overlay the counties:
Here's the outcome from making the adjustments to the state fill and stroke (means that your application of colorScale
for the fill was correct):