Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save Liight/a36cc0a2d47293e4544a4cd795ad659b to your computer and use it in GitHub Desktop.

Select an option

Save Liight/a36cc0a2d47293e4544a4cd795ad659b to your computer and use it in GitHub Desktop.
D3 Choropleth Map (Sass, JavaScript, D3)[FCC]

D3 Choropleth Map (Sass, JavaScript, D3)[FCC]

This is a Choropleth Map coded in D3/JavaScript using some infomational APIs

A Pen by Liight on CodePen.

License.

<div id='main'>
<h1 id='title'>United States Educational Attainment</h1>
<div id='description'>Percentage of adults age 25 and older with a bachelor's degree or higher (2010-2014)</div>
<svg width="960" height="600"></svg>
<div id='source'>Source: <a href='https://www.ers.usda.gov/data-products/county-level-data-sets/download-data.aspx'>USDA Economic Research Service</a></div>
</div>
// Define body
var body = d3.select("body");
// Set Scalable Vector Graphic and 2D Dimensions
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
// Define the div for the tooltip
var tooltip = body.append("div")
.attr("class", "tooltip")
.attr("id", "tooltip")
.style("opacity", 0);
var unemployment = d3.map();
var path = d3.geoPath();
// Set domain and ranges for the scale
var x = d3.scaleLinear()
.domain([2.6, 75.1])
.rangeRound([600, 860]);
var color = d3.scaleThreshold()
.domain(d3.range(2.6, 75.1, (75.1-2.6)/8))
.range(d3.schemeGreens[9]);
// Display Map Legend
var g = svg.append("g")
.attr("class", "key")
.attr("id", "legend")
.attr("transform", "translate(0,40)");
// Returns the extent of values in the domain [x0, x1] for the corresponding value in the range, representing the inverse mapping from range to domain,
// then appends the rectangles to the svg using the color range to fill them.
g.selectAll("rect")
.data(color.range().map(function(d) {
d = color.invertExtent(d);
if (d[0] == null) d[0] = x.domain()[0];
if (d[1] == null) d[1] = x.domain()[1];
return d;
}))
.enter().append("rect")
.attr("height", 8)
.attr("x", function(d) { return x(d[0]); })
.attr("width", function(d) { return x(d[1]) - x(d[0]); })
.attr("fill", function(d) { return color(d[0]); });
// Set text attributes
g.append("text")
.attr("class", "caption")
.attr("x", x.range()[0])
.attr("y", -6)
.attr("fill", "#000")
.attr("text-anchor", "start")
.attr("font-weight", "bold")
// Append ticks as int%
g.call(d3.axisBottom(x)
.tickSize(13)
.tickFormat(function(x) { return Math.round(x) + '%' })
.tickValues(color.domain()))
.select(".domain")
.remove();
const EDUCATION_FILE = 'https://raw.githubusercontent.com/no-stack-dub-sack/testable-projects-fcc/master/src/data/choropleth_map/for_user_education.json';
const COUNTY_FILE = 'https://raw.githubusercontent.com/no-stack-dub-sack/testable-projects-fcc/master/src/data/choropleth_map/counties.json';
// Load if no error is thrown
d3.queue()
.defer(d3.json, COUNTY_FILE)
.defer(d3.json, EDUCATION_FILE)
.await(ready);
// define ready for the queue check
function ready(error, us, education) {
if (error) throw error;
// TopoJSON is an extension of GeoJSON that encodes topology.
// Give County Ids from the API
// Get education data and pass into each county element
// Display info tooltip on mouseover
// Apply tooltip styles
svg.append("g")
.attr("class", "counties")
.selectAll("path")
.data(topojson.feature(us, us.objects.counties).features)
.enter().append("path")
.attr("class", "county")
.attr("data-fips", function(d) {
return d.id
})
.attr("data-education", function(d) {
var result = education.filter(function( obj ) {
return obj.fips == d.id;
});
if(result[0]){
return result[0].bachelorsOrHigher
}
//could not find a matching fips id in the data
console.log('could find data for: ', d.id);
return 0
})
.attr("fill", function(d) {
var result = education.filter(function( obj ) {
return obj.fips == d.id;
});
if(result[0]){
return color(result[0].bachelorsOrHigher)
}
//could not find a matching fips id in the data
return color(0)
})
.attr("d", path)
.on("mouseover", function(d) {
tooltip.style("opacity", .9);
tooltip.html(function() {
var result = education.filter(function( obj ) {
return obj.fips == d.id;
});
if(result[0]){
return result[0]['area_name'] + ', ' + result[0]['state'] + ': ' + result[0].bachelorsOrHigher + '%'
}
//could not find a matching fips id in the data
return 0
})
.attr("data-education", function() {
var result = education.filter(function( obj ) {
return obj.fips == d.id;
});
if(result[0]){
return result[0].bachelorsOrHigher
}
//could not find a matching fips id in the data
return 0
})
.style("left", (d3.event.pageX + 10) + "px")
.style("top", (d3.event.pageY - 28) + "px"); })
.on("mouseout", function(d) {
tooltip.style("opacity", 0);
});
// Append states to the SVG element.
svg.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; }))
.attr("class", "states")
.attr("d", path);
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
html, body {
padding: 0;
margin: 0;
}
body {
display: flex;
justify-content: center;
font-family: 'Arial';
}
#main {
width: 1000px;
display: flex;
padding-top: 1rem;
flex-direction: column;
align-items: center;
}
.counties {
fill: none;
}
.states {
fill: none;
stroke: #fff;
stroke-linejoin: round;
}
div.tooltip {
position: absolute;
padding: 10px;
font: 12px Arial;
background: rgba(255, 255, 204, 0.9);
box-shadow: 1px 1px 10px rgba(128, 128, 128, 0.6);
border: 0px;
border-radius: 2px;
pointer-events: none;
}
#title {
font-size: 3.5rem;
}
#description {
text-align: center;
}
#source {
align-self: flex-end;
margin-top: 1rem;
}
a {
text-decoration: none;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment