Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save mattrelph/7682d6b49e6f67b0cb12bfd000a71b86 to your computer and use it in GitHub Desktop.
Save mattrelph/7682d6b49e6f67b0cb12bfd000a71b86 to your computer and use it in GitHub Desktop.
FCC - Data Visualization Projects - Visualize Data with a Bar Chart

FCC - Data Visualization Projects - Visualize Data with a Bar Chart

User Story #1: My chart should have a title with a corresponding id="title". User Story #2: My chart should have a g element x-axis with a corresponding id="x-axis". User Story #3: My chart should have a g element y-axis with a corresponding id="y-axis". User Story #4: Both axes should contain multiple tick labels, each with the corresponding class="tick". User Story #5: My chart should have a rect element for each data point with a corresponding class="bar" displaying the data. User Story #6: Each bar should have the properties data-date and data-gdp containing date and GDP values. User Story #7: The bar elements' data-date properties should match the order of the provided data. User Story #8: The bar elements' data-gdp properties should match the order of the provided data. User Story #9: Each bar element's height should accurately represent the data's corresponding GDP. User Story #10: The data-date attribute and its corresponding bar element should align with the corresponding value on the x-axis. User Story #11: The data-gdp attribute and its corresponding bar element should align with the corresponding value on the y-axis. User Story #12: I can mouse over an area and see a tooltip with a corresponding id="tooltip" which displays more information about the area. User Story #13: My tooltip should have a data-date property that corresponds to the data-date of the active area.

A Pen by Matthew Relph on CodePen.

License.

<div class = "container">
<div class = "row">
<div class="col">
</div>
<div class="col-10 text-center">
<div class="infoGraphic card">
<div class="card-body">
<h5 id="title" class="card-title h1">United States GDP Over Time</h5>
<p id="graph" class="card-text block-center"></p>
<a href="https://www.bea.gov/national/pdf/nipaguid.pdf" class="btn btn-primary" target="_blank">More Info</a>
</div>
</div>
</div>
<div class="col">
</div>
</div>
</div>
/*Barchart visualization project*/
//Source Dataset - https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/GDP-data.json
//Font Awesome CSS - https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css
//Bootstrap CSS - https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css
//Bootstrap JS - https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js
//D3 Datavisualization Library - https://d3js.org/d3.v5.min.js
//Testing JS - https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js.
document.addEventListener('DOMContentLoaded',function() {
var url = "https://raw.githubusercontent.com/freeCodeCamp/ProjectReferenceData/master/GDP-data.json";
req=new XMLHttpRequest();
req.open("GET",url,true);
req.send();
req.onload=function(){
json=JSON.parse(req.responseText); //Read file data
//Sample small data set for testing
//json = JSON.parse('{"data":[[ "1947-01-01", 243.1 ], [ "1947-04-01", 246.3 ], [ "1947-07-01", 250.1 ], [ "1947-10-01", 260.3 ], [ "1948-01-01", 266.2 ], [ "1948-04-01", 272.9 ], [ "1948-07-01", 279.5 ], [ "1948-10-01", 280.7 ], [ "1949-01-01", 275.4 ]]}');
var dataset = json.data;
//Convert text year data into JS Date objects so they can be plotted
var yearData=[];
for (var i = 0; i<dataset.length; ++i)
{
yearData.push(new Date(dataset[i][0])); //Convert "%Y-%m-%d" to date objects
}
//document.getElementById('graph').innerHTML=JSON.stringify(dataset[0][1]);
const fullwidth = 800;
const fullheight = 600;
const padding = 50;
const width = fullwidth - 2*padding;
const height = fullheight - 2*padding;
//Get the range we want to display on X axis
var maxDate = d3.max(yearData, (d) => d);
var minDate = d3.min(yearData, (d) => d);
var maxDateMore = new Date (maxDate);
var minDateLess = new Date(minDate);
maxDateMore.setMonth(maxDate.getMonth()+3); //Adding a quarter so we have room for last bar on the graph
minDateLess.setMonth(minDate.getMonth()-3); //Subtracting a quarter so we have room at the beginning of the graph
//Get the range we want to display on the Y axis
var maxValue = d3.max(dataset, (d) => d[1]);
var roundedUpMax = Math.ceil(maxValue/1000)*1000; //Round up so the graph doesn't go to the very top
//const barSpacing = 30;
var barPadding = 5;
var barWidth = ((width-padding) / (dataset.length+2) ); //Calculate the width of each bar on the bar graph by dividing up the graph equally amongst the entries, account for the 2 extra quarters
//Define scales
var yScale = d3.scaleLinear()
.domain([0,roundedUpMax])
.range([height, 0]);
var xScale = d3.scaleTime()
.domain([minDateLess, maxDateMore])
.range([padding, width]) ;
//Tests to see if we have read the dataset correctly
//console.log(d3.min(dataset, (d) => d[0]) + " , " + d3.max(dataset, (d) => d[0]));
//console.log(d3.min(dataset, (d) => d[1]) + " , " + d3.max(dataset, (d) => d[1]));
//console.log(dataset.length);
// Define the y and x axis
var yAxis = d3.axisLeft(yScale);
var xAxis = d3.axisBottom(xScale);
//Create SVG
var svg = d3.select("#graph")
.append("svg")
.attr("width", fullwidth)
.attr("height", fullheight);
// Draw y axis
svg.append("g")
.attr("transform", "translate("+padding+",0)")
.attr("id", "y-axis")
.call(yAxis);
// Draw x axis
svg.append("g")
.attr("class", "xaxis")
.attr("id", "x-axis")
.attr("transform", "translate(0," + (height) + ")")
.call(xAxis);
//Add Tooltips
var tooltip = svg.append("text")
.attr("id", "tooltip")
.attr("x", 0.5* width - 100) //Put the info near the middle of the width of the SVG (start slightly to the left of center)
.attr("y", height*0.5) // Put the info at the middle of the height of the SVG
.attr("opacity", 0.9)
.attr("background", "yellow")
.attr("stroke", "black");
//Add bars for bar graph
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("class", "bar")
.attr("x", (d, i) => xScale(yearData[i]))
.attr("y", (d, i) => height - yScale(roundedUpMax-d[1]))
.attr("width", (d, i) => barWidth)
.attr("height", function(d, i){
if (yScale(roundedUpMax-d[1]) <= 0)
{
console.log("height: " + d[1]);
console.log("yscale height: " + yScale(roundedUpMax-d[1])); //Check for proper scaling
return 1;
}
else
{
return yScale(roundedUpMax-d[1]);
}
})
.attr('data-date', (d,i) => (d[0]))
.attr('data-gdp', (d,i) => (d[1]))
.attr("fill", "LightBlue")
.on('mouseover', function(d, i) {
tooltip.text(d[0] + ": $" + d[1] + " Billions of Dollars")
.attr('data-date', d[0])
.attr('opacity', 0.9);
})
.on('mouseout', function(d) {
tooltip.attr('opacity', 0);
})
//Add tooltips near mouse
.append("title")
.text ((d,i) => d[0] + ": $" + d[1] + " Billions of Dollars")
.attr("data-date",(d,i) => (d[0]));
}
});
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://cdn.freecodecamp.org/testable-projects-fcc/v1/bundle.js"></script>
body {
margin-top: 50px;
background : LightGray;
}
.infoGraphic{
background : white;
padding: 10px;
box-shadow: 10px 10px;
}
.tooltipBox{
font: 18px sans-serif;
background-color: yellow;
text-align: center;
padding: 3px;
margin: 1px;
color: black;
}
.bar:hover{
fill: green;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" />
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment