freeCodeCamp : Visualize Data with a Heat Map
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900" rel="stylesheet" />
body {
background-color: #eee;
}
svg {
background-color: #fff;
}
rect {
stroke-width: 0px;
cursor: pointer;
}
.graph-title {
font-family: Roboto, sans-serif;
font-size: 1.9em;
font-weight: 700;
text-align: center;
padding-top: 10px;
padding-bottom: 0px;
color: #333;
}
.graph-subtitle {
font-family: Roboto, sans-serif;
font-size: 1.4em;
font-weight: 500;
text-align: center;
padding-top: 0px;
padding-bottom: 0px;
color: #555;
}
text.scales {
font-family: Roboto, sans-serif;
font-size: 0.75em;
font-weight: 300;
}
.axis text {
font-family: Roboto, sans-serif;
font-size: 0.75em;
font-weight: 300;
}
.axis path, .axis line {
fill: none;
stroke: #111;
shape-rendering: crispEdges;
}
.axislabel{
font-family: Roboto, sans-serif;
font-size: 1em;
font-weight: 500;
}
#chart {
background-color: white;
}
.card {
background-color: white;
margin: 40px auto;
padding: 0px;
width: 1250px;
height: 670px;
box-shadow: 0 3px 6px 0 rgba(0, 0, 0, 0.32), 0 3px 12px 0 rgba(0, 0, 0, 0.24);
}
.tooltip {
position: absolute;
text-align: center;
width: auto;
height: auto;
padding: 3px 5px 3px 5px;
font: 1em sans-serif;
border: 0px;
border-radius: 5px;
pointer-events: none;
box-shadow: 3px 3px 6px rgba(0, 0, 0, 0.2);
background-color: black;
}
.year {
font-family: Roboto, sans-serif;
font-size: 1.1em;
font-weight: bold;
color: white;
white-space: nowrap;
}
.temperature {
font-family: Roboto, sans-serif;
font-size: 0.95em;
font-weight: bolder;
color: white;
white-space: nowrap;
}
.variance {
font-family: Roboto, sans-serif;
font-size: 0.8em;
font-weight: normal;
color: white;
white-space: nowrap;
}
.details {
font-family: Roboto, sans-serif;
font-size: 0.7em;
font-weight: 300;
text-align: center;
padding: 0px;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script>
// temperature data URL
var URL_temperatureData = 'https://raw.githubusercontent.com/FreeCodeCamp/ProjectReferenceData/master/global-temperature.json';
var month = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
var colors = ["#5e4fa2", "#3288bd", "#66c2a5", "#abdda4", "#e6f598", "#ffffbf", "#fee08b", "#fdae61", "#f46d43", "#d53e4f", "#9e0142"];
var buckets = colors.length;
var margin = {
top: 5,
right: 0,
bottom: 90,
left: 100
};
var width = 1200 - margin.left - margin.right;
var height = 550 - margin.top - margin.bottom;
var legendElementWidth = 35;
var axisYLabelX = -65;
var axisYLabelY = height / 2;
var axisXLabelX = width / 2;
var axisXLabelY = height + 45;
d3.json(URL_temperatureData, function(error, data) {
if (error) throw error;
var baseTemp = data.baseTemperature;
var temperatureData = data.monthlyVariance;
var yearData = temperatureData.map(function(obj) {
return obj.year;
});
yearData = yearData.filter(function(v, i) {
return yearData.indexOf(v) == i;
});
var varianceData = temperatureData.map(function(obj) {
return obj.variance;
});
var lowVariance = d3.min(varianceData);
var highVariance = d3.max(varianceData);
var lowYear = d3.min(yearData);
var highYear = d3.max(yearData);
var minDate = new Date(lowYear, 0);
var maxDate = new Date(highYear, 0);
var gridWidth = width / yearData.length;
var gridHeight = height / month.length;
var colorScale = d3.scale.quantile()
.domain([lowVariance + baseTemp, highVariance + baseTemp])
.range(colors);
var svg = d3.select("#chart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var div = d3.select("#chart").append("div")
.attr("class", "tooltip")
.style("opacity", 0);
var monthLabels = svg.selectAll(".monthLabel")
.data(month)
.enter()
.append("text")
.text(function(d) {
return d;
})
.attr("x", 0)
.attr("y", function(d, i) {
return i * gridHeight;
})
.style("text-anchor", "end")
.attr("transform", "translate(-6," + gridHeight / 1.5 + ")")
.attr("class", "monthLabel scales axis axis-months");
var xScale = d3.time.scale()
.domain([minDate, maxDate])
.range([0, width]);
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(d3.time.years, 10);
svg.append("g")
.attr("class", "axis axis-years")
.attr("transform", "translate(0," + (height + 1) + ")")
.call(xAxis);
svg.append('g')
.attr('transform', 'translate(' + axisYLabelX + ', ' + axisYLabelY + ')')
.append('text')
.attr('text-anchor', 'middle')
.attr('transform', 'rotate(-90)')
.attr("class", "axislabel")
.text('Months');
svg.append('g')
.attr('transform', 'translate(' + axisXLabelX + ', ' + axisXLabelY + ')')
.append('text')
.attr('text-anchor', 'middle')
.attr("class", "axislabel")
.text('Years');
var temps = svg.selectAll(".years")
.data(temperatureData, function(d) {
return (d.year + ':' + d.month);
});
temps.enter()
.append("rect")
.attr("x", function(d) {
return ((d.year - lowYear) * gridWidth);
})
.attr("y", function(d) {
return ((d.month - 1) * gridHeight);
})
.attr("rx", 0)
.attr("ry", 0)
.attr("width", gridWidth)
.attr("height", gridHeight)
.style("fill", "white")
.on("mouseover", function(d) {
div.transition()
.duration(100)
.style("opacity", 0.8);
div.html("<span class='year'>" + d.year + " - " + month[d.month - 1] + "</span><br>" +
"<span class='temperature'>" + (Math.floor((d.variance + baseTemp) * 1000) / 1000) + " ℃" + "</span><br>" +
"<span class='variance'>" + d.variance + " ℃" + "</span>")
.style("left", (d3.event.pageX - ($('.tooltip').width()/2)) + "px")
.style("top", (d3.event.pageY - 75) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(200)
.style("opacity", 0);
});
temps.transition().duration(1000)
.style("fill", function(d) {
return colorScale(d.variance + baseTemp);
});
var legend = svg.selectAll(".legend")
.data([0].concat(colorScale.quantiles()), function(d) {
return d;
});
legend.enter().append("g")
.attr("class", "legend");
legend.append("rect")
.attr("x", function(d, i) {
return legendElementWidth * i + (width - legendElementWidth * buckets);
})
.attr("y", height + 50)
.attr("width", legendElementWidth)
.attr("height", gridHeight / 2)
.style("fill", function(d, i) {
return colors[i];
});
legend.append("text")
.attr("class", "scales")
.text(function(d) {
return (Math.floor(d * 10) / 10);
})
.attr("x", function(d, i) {
return ((legendElementWidth * i) + Math.floor(legendElementWidth / 2) - 6 + (width - legendElementWidth * buckets));
})
.attr("y", height + gridHeight + 50);
});
<meta charset="utf-8">
<html>
<head>
<title>Monthly Global Temperature</title>
</head>
<body>
<div class="card">
<div class="graph-title">Monthly Global Land-Surface Temperature</div>
<div class="graph-subtitle">1753 - 2015</div>
<div class="details">Temperatures are in Celsius and reported as anomalies relative to the Jan 1951-Dec 1980 average.<br>Estimated Jan 1951-Dec 1980 absolute temperature ℃: 8.66 +/- 0.07</div>
<div id="chart"></div>
</div>
</body>
</html>
Forked from Bruce Young's Pen D3 Zipline: Global Temperature Heat Map.
Forked from Free Code Camp's Pen D3 Zipline: Global Temperature Heat Map.
Forked from Jonathan Graham's Pen D3 Zipline: Global Temperature Heat Map.
A Pen by HARUN PEHLİVAN on CodePen.