Created
January 26, 2017 10:04
-
-
Save chemok78/75b776ecefc163b9aca5106449053671 to your computer and use it in GitHub Desktop.
Heatmap D3 JS - Monthly Global Land-Surface Temperature
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var url = "https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/global-temperature.json" | |
d3.json(url, function(json){ | |
//load data from API and save in variables | |
var data = json.monthlyVariance; | |
var baseTemp = json.baseTemperature; | |
//global variable for the months to be accessed like months[i] | |
var months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; | |
//Add temperature and month as string, to each object in data set | |
for(var i = 0; i < data.length; i++){ | |
var temperature = baseTemp + data[i].variance | |
data[i].temperature = temperature; | |
var monthString = ""; | |
switch(data[i].month){ | |
case 1: | |
data[i].monthString = "January"; | |
break; | |
case 2: | |
data[i].monthString = "February"; | |
break; | |
case 3: | |
data[i].monthString = "March"; | |
break; | |
case 4: | |
data[i].monthString = "April"; | |
break; | |
case 5: | |
data[i].monthString = "May"; | |
break; | |
case 6: | |
data[i].monthString = "June"; | |
break; | |
case 7: | |
data[i].monthString = "July"; | |
break; | |
case 8: | |
data[i].monthString = "August"; | |
break; | |
case 9: | |
data[i].monthString = "September"; | |
break; | |
case 10: | |
data[i].monthString = "October"; | |
break; | |
case 11: | |
data[i].monthString = "November"; | |
break; | |
case 12: | |
data[i].monthString = "December"; | |
break; | |
} | |
} | |
//Set dimensions of div container, svg, and chart area(g element) | |
var margin = {top: 40, right: 60, bottom: 100, left: 100}; | |
//Width of the chart, within SVG element | |
var w = 1000 - margin.left - margin.right; | |
//Height of the chart, within SVG element | |
var h = 600 - margin.top - margin.bottom; | |
//Create SVG element and append to #chart div container | |
//SVG is nested G element | |
var svg = d3.select("#chart") | |
.append("svg") | |
.attr("width", w + margin.left + margin.right) | |
.attr("height", h + margin.top + margin.bottom) | |
.append("g") | |
.attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
//Get Min Max values | |
var maxYear = d3.max(data, function(d){ | |
return d.year; | |
}); | |
var minYear = d3.min(data, function(d){ | |
return d.year; | |
}); | |
var maxTemp = d3.max(data, function(d){ | |
return d.temperature; | |
}); | |
var minTemp = d3.min(data, function(d){ | |
return d.temperature; | |
}) | |
//Create X scale, axis and label | |
var xScale = d3.scaleLinear() | |
.domain([minYear, maxYear]) | |
.range([0,w]); | |
var xAxis = d3.axisBottom() | |
.scale(xScale) | |
.ticks(20) | |
//remove the comma for thousands by using tickFormat | |
.tickFormat(d3.format("d")); | |
//move X axis to bottom of chart area | |
svg.append("g") | |
.attr("class", "axis") | |
.attr("transform", "translate(0," + h + ")") | |
.call(xAxis); | |
var xLabel = svg.append("text") | |
.text("Year") | |
//place x label halfway X axis and between chart area and container div | |
.attr("x", w/2) | |
.attr("y", h + (margin.bottom/2.5)) | |
.attr("font-size", "14px" ); | |
//Create Y scale, axis and label | |
//Each cell's height is height of chart divided by 12 months | |
var cellHeight = (h / 12); | |
//Will use ordinal scale for Y. Divide the range in 12 segments and save in array | |
var yRange = []; | |
for(var i = 0; i < 12 ; i++){ | |
yRange.push(i * cellHeight); | |
} | |
var yScale = d3.scaleOrdinal() | |
//map 12 months to 12 segments of height | |
.domain(months) | |
.range(yRange); | |
var yAxis = d3.axisLeft() | |
.scale(yScale) | |
.ticks(12); | |
svg.append("g") | |
//append a g element | |
.attr("class", "axis") | |
.call(yAxis) | |
//call yAxis function on this g element | |
.selectAll(".tick text") | |
//select all elements with class tick and nested text element | |
.attr("transform", "translate(0," + (cellHeight/2) + ")"); | |
//move all text elements half a cell height down | |
var yLabel = svg.append("text") | |
//rotate yLabel and x and y rotate too | |
.attr("transform", "rotate(-90)") | |
.attr("x", 0 - (h/2)) | |
.attr("y", 0 - (margin.left/1.8)) | |
.style("font-size", "14px") | |
.style("text-anchor", "middle") | |
.text("Month"); | |
//Create color scale | |
var colorCodes = ["#5E4FA2", "#3288BD", "#66C2A5", "#ABDDA4", "#E6F598", "#FFFFBF", "#FEE08B", "#FDAE61", "#F46D43", "#D53E4F", "#9E0142"]; | |
var colors = d3.scaleQuantile() | |
//quantile scale divides domain in bands according to ordinal scale range | |
.domain([minTemp,maxTemp]) | |
.range(colorCodes); | |
var colorQuantiles = colors.quantiles(); | |
colorQuantiles.unshift(0); | |
//save the upper ranges of each temperature quantile + 0 at the beginning (quantile function does not count 0 as start) | |
//Append tooltip to chart area. Fully transparant at first. Use mouse events to show: making less opaque | |
var tip = d3.select("#chart").append("div") | |
.attr("class", "tooltip") | |
.style("opacity", 0); | |
//Create the cells for each month/year/temperature combo | |
//Select all rect elements in G container element, bind data and append | |
var cells = svg.selectAll("cells") | |
.data(data) | |
.enter() | |
.append("rect"); | |
var cellAttributes = cells | |
.attr("x", function(d){ | |
return xScale(d.year); | |
}) | |
.attr("y", function(d){ | |
return yScale(d.monthString); | |
}) | |
.attr("width", w/(maxYear-minYear)) | |
.attr("height", cellHeight) | |
.attr("fill", function(d){ | |
return colors(d.temperature); | |
}) | |
.attr("class", "cell") | |
.on("mouseover", function(d){ | |
//show tooltip on mouseover | |
tip.transition() | |
.style("opacity", 0.7); | |
tip.html("<strong>" + months[d.month-1] + " - " + d.year + "</strong><br>" + d.temperature.toFixed(2) + " °C<br>" + d.variance.toFixed(2) + " °C") | |
.style("left", d3.event.pageX + "px") | |
.style("top", d3.event.pageY - 70 + "px"); | |
}) | |
.on("mouseout", function(d){ | |
tip.transition() | |
.style("opacity", 0); | |
}) | |
//Create a legend | |
var blockWidth = 35; | |
var blockHeight = 20; | |
var legend = svg.selectAll(".legend") | |
//each block = color in legend is a g element and shifted to the right using the blockwidth | |
.data(colorQuantiles) | |
.enter() | |
.append("g") | |
.attr("class", "legend") | |
.attr("font-size", "14px") | |
.attr("font-style", "PT Sans") | |
.attr("transform", function(d,i){ | |
return ("translate(" + i * blockWidth + ",0)") | |
}); | |
//append to each legend g element a rect element | |
legend.append("rect") | |
.attr("x", (w/5) * 3 ) | |
.attr("y", h + (margin.bottom/3)) | |
.attr("width", blockWidth) | |
.attr("height", blockHeight) | |
.style("fill", function(d,i){ | |
return(colorCodes[i]); | |
}); | |
legend.append("text") | |
.attr("x", ((w/5) * 3) + (blockWidth/2) ) | |
.attr("y", (h+ (margin.bottom/3)) + blockHeight + 15 ) | |
.text(function(d,i){ | |
return colorQuantiles[i].toFixed(1); | |
}) | |
.style("text-anchor", "middle"); | |
})//d3.json |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<head> | |
<meta charset="utf-8"> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge"> | |
<meta name="viewport" content="width=device-width, initial-scale=1"> | |
<link href="https://fonts.googleapis.com/css?family=PT+Sans" rel="stylesheet"> | |
<head> | |
<body> | |
<div class="container text-center"> | |
<h1>Monthly Global Land-Surface Temperature</h1> | |
<h2>1753 - 2015 </h2> | |
<p>Temperatures are in Celsius and reported as anomalies relative to the Jan 1951-Dec 1980 average. | |
Estimated Jan 1951-Dec 1980 absolute temperature ℃: 8.66 +/- 0.0</p> | |
</br> | |
<div id="chart"> | |
</div | |
</div> | |
</body> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
body { | |
margin-top: 20px; | |
font-family: 'PT Sans', sans-serif; | |
background-image: url("https://subtlepatterns.com/patterns/sos.png"); | |
} | |
svg { | |
background-color: white; | |
box-shadow: 0 0 10px #888888; | |
} | |
.axis path, | |
line { | |
fill: none; | |
stoke: black; | |
shape-rendering: crispEdges | |
} | |
.axis text { | |
font-family: PT Sans; | |
font-size: 12px; | |
} | |
.tooltip { | |
position: absolute; | |
text-align: center; | |
vertical-align: middle; | |
width: 140px; | |
height: 70px; | |
padding: 5px; | |
font: 14px PT Sans; | |
background: #2c3e50; | |
border: 0px; | |
border-radius: 8px; | |
color: white; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment