div#choropleth{
text-align:center;
align-items:center;
}
.county{
stroke: rgba(11,156,49, .2)
}
#title{
font-size:1.5rem;
}
#tooltip{
position:absolute;
background:rgba(0, 0, 0, 0.6);
color:white;
padding:5px;
border-radius:10px;
}
a:hover{
text-decoration:none;
}
#about{
max-width:992px;
}
#source a{
fill:blue;
}
#choropleth{
overflow-x:scroll;
}
class App extends React.Component{
render(){
return (
<div id="app">
<Header />
<ChoroplethMap />
<About />
<Footer />
</div>
)
}
}
const Header =()=>{return (
<header className="bg-dark p-2 mb-4">
<div className='d-flex justify-content-center container'>
<h1 className="text-light">D3js Choropleth Map</h1>
</div>
</header>
)};
const Footer =()=>{return (
<footer className="bg-dark p-3 mt-4">
<div className='d-flex justify-content-center align-items-center container'>
<span className="text-light text-center">Developer :
<a href="https://www.linkedin.com/in/thetradecoder/" className="nav-link">theTradeCoder</a>
</span>
</div>
</footer>
)};
const About = () =>{
return(
<div id="about" className="container mt-3 pt-3 bt-3 mb-3">
<h2>About : </h2>
<p><a href="https://freecodecamp.com">- freeCodeCamp Data Visualization Project</a><br/>
- Data Visualization with Choropleth Map <br/>
- A D3js and Reactjs Project
</p>
</div>
)
};
class ChoroplethMap extends React.Component{
render(){
const urlEdu = "https://cdn.freecodecamp.org/testable-projects-fcc/data/choropleth_map/for_user_education.json";
const urlCounty = "https://cdn.freecodecamp.org/testable-projects-fcc/data/choropleth_map/counties.json";
d3.queue()
.defer(d3.json, urlEdu)
.defer(d3.json, urlCounty)
.await((err, edu, county)=>{
const w = 992;
const h = 650;
const pad = 60;
const svg = d3.select('#choropleth')
.append('svg')
.attr('width', w)
.attr('height', h)
.style('background-color', '#DDE8DA');
const tooltip = d3.select('#choropleth')
.append('div')
.attr('id','tooltip')
.style('opacity', 0);
const path = d3.geoPath();
const bachelorHigherHighLow = d3.extent(edu.map(d=>d.bachelorsOrHigher));
const low = bachelorHigherHighLow[0];
const high = bachelorHigherHighLow[1];
const topoData = topojson.feature(county, county.objects.counties).features;
const colors = d3.scaleThreshold()
.domain(d3.range(low, high, (high-low)/9))
.range(d3.schemeGreens[9]);
svg.append('g')
.selectAll('path')
.data(topoData)
.enter()
.append('path')
.attr('class', 'county')
.attr('d', path)
.attr('fill', (d)=>{
let eduMatch = edu.filter((data)=>data.fips==d.id);
if(eduMatch[0]){
return colors(eduMatch[0].bachelorsOrHigher)
}
return 0;
})
.attr('data-fips', (d)=>d.id)
.attr('data-education', (d)=>{
let eduMatch = edu.filter((data)=>data.fips==d.id);
if(eduMatch[0]){
return eduMatch[0].bachelorsOrHigher
}
return 0;
})
.on('mouseover', (d,i)=>{
tooltip.style('opacity', 1)
.style('left', (d3.event.pageX+30)+'px')
.style('top', (d3.event.pageY-20)+'px')
.attr('data-education', ()=>{
let eduMatch = edu.filter(data=>data.fips==d.id);
if(eduMatch[0]){
return eduMatch[0].bachelorsOrHigher;
}
return 0;
})
.html(()=>{
let eduMatch = edu.filter(data=>data.fips==d.id);
if(eduMatch[0]){return `${eduMatch[0].area_name}, ${eduMatch[0].state}<br/> ${eduMatch[0].bachelorsOrHigher}%`}
return 0;
})
})
.on('mouseout', (d)=>{
tooltip.style('opacity', 0)
.style('left', 0)
.style('top', 0)
});
svg.append('text')
.attr('id', 'title')
.text('US Educational Attainment')
.attr('x', w/3)
.attr('y', 25);
svg.append('text')
.attr('id', 'description')
.text("Percentage of adults age 25 and older with a bachelor\'s degree or higher (2010-2014)")
.attr('x', w/5)
.attr('y', 40);
const xScale = d3.scaleLinear()
.domain([low, high])
.range([pad, w/2-pad]);
const xAxis = d3.axisBottom(xScale)
.tickSize(25)
.tickFormat(d=>Math.round(d)+'%')
.tickValues(colors.domain());
svg.append('g')
.attr('id', 'x-axis')
.attr('transform', 'translate('+(w/3)+','+(h-pad)+')')
.call(xAxis)
.select('.domain')
.remove();
svg.append('g')
.attr('id', 'legend')
.selectAll('rect')
.data(colors.range().map(d=>d))
.enter()
.append('rect')
.attr('height', 15)
.attr('width', (d, i)=>(w/2-pad*2)/9)
.attr('fill', d=>d)
.attr('x', (d,i)=>(pad+w/3)+(i*((w/2-pad*2)/9)))
.attr('y', h-pad);
svg.append('g')
.attr('id', 'source')
.append('text')
.html('Data Source: <a href="https://cdn.freecodecamp.org/testable-projects-fcc/data/choropleth_map/for_user_education.json">U.S. Education Data</a>')
.attr('x', pad)
.attr('y', h-pad+10)
})
return(
<div id="choropleth">
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('content'))
View Compiled