First, I organized my files and got my data.
Next, I moved on to the basic index.html skeleton with navbar to hold my visualization.
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<meta name='viewport' content='width=device-width, initial-scale=1.0'>
<meta http-equiv='X-UA-Compatible' content='ie=edge'>
<title>D3 Visualizations</title>
<script src='https://code.jquery.com/jquery-3.3.1.slim.min.js' integrity='sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo'
crossorigin='anonymous'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js' integrity='sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49'
crossorigin='anonymous'></script>
<script src='https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js' integrity='sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy'
crossorigin='anonymous'></script>
<link rel='stylesheet' href='https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css' integrity='sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO'
crossorigin='anonymous'>
<link rel='stylesheet' href='assets/css/style.css'>
<link rel='stylesheet' href='assets/css/d3Style.css'>
</head>
<body>
<nav class='navbar navbar-custom'>
<a class='navbar-brand' href='index.html'>United States Poverty and Obesity Trends</a>
</div>
</nav>
<div class='container-fluid'>
<div class='row'>
<div class='col text-center'>
<h4 id='plot-title'>Poverty vs. Obesity Across 50 States</h4>
</div>
</div>
<div class='row'>
<div class='col text-center'>
<div id='scatter'>
</div>
</div>
</div>
<div class='row justify-content-center'>
<div class='col-md-8'>
<div class='row justify-content-center'>
<h5 id='caption'>Correlations Discovered Between Poverty and Obesity</h5>
</div>
<div class='row'><p> This above visualization shows a positive correlation between poverty and obesity.
Poorer states have higher incidences of obesity. The top states showing this correlation are
Mississippi, Louisiana, Alabama, Arkansas, and West Virginia. Other states show healthier populations
along with lower poverty rates, such as Colorado, Hawaii, and Massachusetts. Not all states show this
correlation. For example, North Dakota and Iowa both have relatively high obesity rates compared to
poverty rates.
</p>
</div>
</div>
</div>
</div>
<footer>
<div class='footer'>
Made with 💜 and <a id='d3-link' href='https://d3js.org/' target='_blank' rel='noopener noreferrer'>D3.js</a> | Kathleen Graham 2019
<a href='https://github.com/kathleengraham/interactive-visualizations-with-d3-js' target='_blank' rel='noopener noreferrer'><img id='gh-icon' src='icons8-github-64.png'></a>
</div>
</footer>
<script src='https://cdnjs.cloudflare.com/ajax/libs/d3/5.5.0/d3.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.9.1/d3-tip.js'></script>
<script type='text/javascript' src='assets/js/app.js'></script>
</body>
</html>
Then, I used d3.js to make an interactive visualization that would be rendered on my website using the local server.
// canvas and svg width, height, and margins
const svgWidth = 900
const svgHeight = 450
const margin = {
top: 25,
right: 50,
bottom: 70,
left: 90
}
const width = svgWidth - margin.left - margin.right
const height = svgHeight - margin.top - margin.bottom
// canvas
const svg = d3.select('#scatter').append('svg').attr('width', svgWidth).attr('height',svgHeight)
// chartGroup
const chartGroup = svg.append('g').attr('transform', `translate(${margin.left}, ${margin.top})`)
// data
const dataFile = 'assets/data/data.csv'
d3.csv(dataFile).then(visualization)
// plot function
function visualization(states) {
// data loop
states.map(function (data) {
data.poverty = +data.poverty
data.obesity = +data.obesity
})
// scale fnxs with min and max (plus a little more space)
const linearScaleX = d3.scaleLinear().domain([8,d3.max(states,(d,i)=>d.poverty+0.5)]).range([0, width])
const linearScaleY = d3.scaleLinear().domain([20,d3.max(states,(d,i)=>d.obesity+1)]).range([height, 0])
// call scale fnx with axes fnxs with set tick marks on x axis
const bottomAxis = d3.axisBottom(linearScaleX).ticks(10)
const leftAxis = d3.axisLeft(linearScaleY)
// append axes to chartGroup
chartGroup.append('g').attr('transform', `translate(0, ${height})`).call(bottomAxis)
chartGroup.append('g').call(leftAxis)
// label axes
chartGroup.append('text').attr('transform','rotate(-90)').attr('x',0-height/2).attr('y',0-margin.left+40)
.attr('dy','1em').attr('class','aText').text('Obese (%)')
chartGroup.append('text').attr('transform',`translate(${width/2},${height+margin.top+20})`).attr('class','aText').text('In Poverty (%)')
// create plot markers
let circlesGroup = chartGroup.selectAll('circle').data(states).enter().append('circle')
.attr('cx',d=>linearScaleX(d.poverty)).attr('cy',d=>linearScaleY(d.obesity))
.attr('r','17').attr('fill','#9AAAD1').attr('opacity','0.85')
// add state abbreviations to circles (centered on both x and y of circle)
circlesGroup = chartGroup.selectAll().data(states).enter().append('text')
.attr('x',d=>linearScaleX(d.poverty)).attr('y',(d,i)=>linearScaleY(d.obesity)+4)
.style('font-size','15px').style('text-anchor','middle').style('fill','white').text(d=>(d.abbr))
// make tooltip
const toolTip = d3.tip().attr('class','d3-tip').offset([80,-65])
.html(function(d){return(`<strong>${d.state}</strong><br>Poverty: ${d.poverty}%<br>Obesity: ${d.obesity}%`)})
// add tooltip to chart
chartGroup.call(toolTip)
// tooltip event listeners (show/hide)
circlesGroup.on('mouseover',function(data){toolTip.show(data,this)})
.on('mouseout',function(data){toolTip.hide(data)})
}
Last, I added styles to give a little bit more personalization.
.navbar-custom {
background-color: #9AAAD1;
}
.navbar-brand:link,
.navbar-brand:visited,
.navbar-brand:hover,
.navbar-brand:active {
color: white;
font-size: 0.9em;
}
#plot-title {
padding-top: 10px;
}
#caption {
text-align: center;
}
footer {
background-color: #9AAAD1;
color: white;
font-size: 9pt;
text-align: center;
vertical-align: middle;
line-height: 45px;
position: fixed;
left: 0;
bottom: 0;
width: 100%;
}
footer p {
margin: 0;
font-size: 0.9em;
}
#d3-link:link,
#d3-link:visited,
#d3-link:hover,
#d3-link:active {
color: white !important;
}
#gh-icon {
width: 30px;
height: 30px;
background-size: 100%;
}
And I styled my D3 Visualization with its own .css file.
.aText {
font-family: sans-serif;
font-size: 16px;
text-anchor: middle;
}
.active {
font-weight: bold;
fill: #000;
transition: fill 0.3s ease-out;
text-anchor: middle;
}
.inactive {
font-weight: lighter;
fill: #c9c9c9;
transition: fill 0.3s ease-out;
text-anchor: middle;
}
.inactive:hover {
fill: #000;
cursor: pointer;
}
/* font size dependent on radius, see app.js */
.stateText {
font-family: sans-serif;
fill: #fff;
text-anchor: middle;
}
.stateCircle {
fill: #89bdd3;
stroke: #e3e3e3;
}
.chart {
display: block;
margin: 0;
}
.d3-tip {
padding: 10px;
font-size: 14px;
line-height: 1;
line-height: 1.5em;
color: #fff;
text-align: center;
background: rgba(0, 0, 0, 0.8);
border-radius: 4px;
}
/* Mobile Rules */
@media screen and (max-width: 530px) {
.stateText {
display: none;
}
.aText {
font-size: 14px;
}
}
@media screen and (max-width: 400px) {
.aText {
font-size: 13px;
}
}