harunpehlivan
3/6/2018 - 11:36 PM

freeCodeCamp : Visualize Data with a Heat Map

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) + " &#8451" + "</span><br>" +
          "<span class='variance'>" + d.variance + " &#8451" + "</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 &#8451: 8.66 +/- 0.07</div>
    <div id="chart"></div>
  </div>



</body>

</html>