Skip to content

Instantly share code, notes, and snippets.

@sergixnet
Last active May 1, 2019 16:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sergixnet/40478a9df5c3adba2d0433d349a69607 to your computer and use it in GitHub Desktop.
Save sergixnet/40478a9df5c3adba2d0433d349a69607 to your computer and use it in GitHub Desktop.
FCC: D3 Bar Chart
<main class="main">
<section class="container">
<h1 id="title">United States GDP</h1>
<svg width="900" height="500" class="visualization"></svg>
</section>
</main>
const {
select,
json,
scaleLinear,
scaleTime,
axisLeft,
axisBottom,
timeFormat,
min,
max
} = d3;
const svg = select('.visualization');
const width = +svg.attr('width');
const height = +svg.attr('height');
const tooltip = select('body').append('div')
.attr('id', 'tooltip')
.style('opacity', 0);
const getQuarterDate = d => {
const date = d[0];
const year = date.split('-')[0];
const month = date.split('-')[1]
let quarter = '';
switch (month) {
case '01':
quarter = 'Q1';
break;
case '04':
quarter = 'Q2';
break;
case '07':
quarter = 'Q3';
break;
case '10':
quarter = 'Q4';
break;
default:
quarter = 'Q1'
}
return `${year} - ${quarter}`;
}
const showTooltip = d => {
const x = d3.event.pageX;
const y = d3.event.pageY;
tooltip.transition()
.duration(200)
.style('opacity', 1);
const html = `
<span>${getQuarterDate(d)}</span>
<br>
<span>$${d[1]} Billion</span>`;
tooltip.html(html)
.attr('class', 'tooltip')
.attr('data-date', d[0])
.style('left', `${x + 20}px`)
.style('top', `${y - 28}px`)
};
const hideTooltip = d => {
tooltip.transition()
.duration(200)
.style('opacity', 0);
};
const render = data => {
const dataset = data.data;
const margin = {top: 20, bottom: 20, left: 50, right: 50};
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
const barWidth = innerWidth / dataset.length;
const yBarsScale = scaleLinear()
.domain([0, max(dataset)[1]])
.range([0, innerHeight]);
const barHeight = d => yBarsScale(d[1]);
const barsArea = svg.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top})`);
barsArea.selectAll('rect').data(dataset)
.enter().append('rect')
.attr('x', (d, i) => i * barWidth)
.attr('y', d => innerHeight - yBarsScale(d[1]))
.attr('width', barWidth)
.attr('height', barHeight )
.attr('class', 'bar')
.attr('data-date', d => d[0])
.attr('data-gdp', d => d[1])
.on('mouseover', showTooltip)
.on('mouseout', hideTooltip)
const yAxisScale = scaleLinear()
.domain([0, max(dataset)[1]])
.range([innerHeight, 0]);
const minYear = min(dataset, (d) => d[0]);
const maxYear = max(dataset, (d) => d[0]);
const xAxisScale = scaleTime()
.domain([new Date(minYear), new Date(maxYear)])
.range([0, innerWidth])
const yAxisG = svg.append('g')
.call(axisLeft(yAxisScale))
.attr('transform', `translate(${margin.left}, ${margin.top})`)
.attr('id', 'y-axis');
const xAxisG = axisBottom(xAxisScale).tickFormat(timeFormat('%Y'));
svg.append('g')
.attr('id', 'x-axis')
.attr('transform', `translate(${margin.left}, ${margin.top + innerHeight})`)
.call(xAxisG)
}
d3.json('https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/GDP-data.json').then(render)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.9.2/d3.min.js"></script>
<script src="https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js"></script>
@import url('https://fonts.googleapis.com/css?family=Open+Sans:400,600');
* {
&,
&:before,
&:after {
box-sizing: border-box;
}
}
body {
font-family: 'Open Sans', sans-serif;
font-weight: 400;
background-color: #cabada;
}
.main {
width: 100%;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.container {
background-color: #fff;
padding: 2rem;
box-shadow: 0 0 20px rgba(black, 0.5);
}
#title {
font-weight: 600;
text-align: center;
}
.bar {
fill: steelblue;
&:hover {
fill: lightblue;
}
}
.tooltip {
position: absolute;
text-align: center;
line-height: 1.4;
font-size: 0.85rem;
padding: 1em;
background-color: #fff;
box-shadow: 0 0 10px black;
pointer-events: none;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment