Skip to content

Instantly share code, notes, and snippets.

@jalapic
Last active April 11, 2016 03:01
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 jalapic/36212013e18788087719e861742e6495 to your computer and use it in GitHub Desktop.
Save jalapic/36212013e18788087719e861742e6495 to your computer and use it in GitHub Desktop.
heatmap demo
var accidents=[{"day":1,"hour":0,"count":4},{"day":1,"hour":1,"count":4},{"day":1,"hour":2,"count":9},{"day":1,"hour":3,"count":7},{"day":1,"hour":4,"count":3},{"day":1,"hour":5,"count":0},{"day":1,"hour":6,"count":0},{"day":1,"hour":7,"count":1},{"day":1,"hour":8,"count":0},{"day":1,"hour":9,"count":1},{"day":1,"hour":10,"count":1},{"day":1,"hour":11,"count":0},{"day":1,"hour":12,"count":0},{"day":1,"hour":13,"count":0},{"day":1,"hour":14,"count":18},{"day":1,"hour":15,"count":0},{"day":1,"hour":16,"count":0},{"day":1,"hour":17,"count":0},{"day":1,"hour":18,"count":0},{"day":1,"hour":19,"count":0},{"day":1,"hour":20,"count":2},{"day":1,"hour":21,"count":4},{"day":1,"hour":22,"count":3},{"day":1,"hour":23,"count":0},{"day":2,"hour":0,"count":0},{"day":2,"hour":1,"count":37},{"day":2,"hour":2,"count":19},{"day":2,"hour":3,"count":12},{"day":2,"hour":4,"count":18},{"day":2,"hour":5,"count":15},{"day":2,"hour":6,"count":18},{"day":2,"hour":7,"count":23},{"day":2,"hour":8,"count":19},{"day":2,"hour":9,"count":10},{"day":2,"hour":10,"count":19},{"day":2,"hour":11,"count":21},{"day":2,"hour":12,"count":16},{"day":2,"hour":13,"count":18},{"day":2,"hour":14,"count":6},{"day":2,"hour":15,"count":1},{"day":2,"hour":16,"count":0},{"day":2,"hour":17,"count":4},{"day":2,"hour":18,"count":2},{"day":2,"hour":19,"count":5},{"day":2,"hour":20,"count":8},{"day":2,"hour":21,"count":6},{"day":2,"hour":22,"count":4},{"day":2,"hour":23,"count":8},{"day":3,"hour":0,"count":0},{"day":3,"hour":1,"count":23},{"day":3,"hour":2,"count":7},{"day":3,"hour":3,"count":4},{"day":3,"hour":4,"count":5},{"day":3,"hour":5,"count":0},{"day":3,"hour":6,"count":0},{"day":3,"hour":7,"count":3},{"day":3,"hour":8,"count":12},{"day":3,"hour":9,"count":0},{"day":3,"hour":10,"count":17},{"day":3,"hour":11,"count":1},{"day":3,"hour":12,"count":1},{"day":3,"hour":13,"count":0},{"day":3,"hour":14,"count":0},{"day":3,"hour":15,"count":0},{"day":3,"hour":16,"count":0},{"day":3,"hour":17,"count":0},{"day":3,"hour":18,"count":0},{"day":3,"hour":19,"count":0},{"day":3,"hour":20,"count":2},{"day":3,"hour":21,"count":3},{"day":3,"hour":22,"count":0},{"day":3,"hour":23,"count":3},{"day":4,"hour":0,"count":3},{"day":4,"hour":1,"count":11},{"day":4,"hour":2,"count":10},{"day":4,"hour":3,"count":4},{"day":4,"hour":4,"count":7},{"day":4,"hour":5,"count":0},{"day":4,"hour":6,"count":1},{"day":4,"hour":7,"count":4},{"day":4,"hour":8,"count":1},{"day":4,"hour":9,"count":7},{"day":4,"hour":10,"count":10},{"day":4,"hour":11,"count":6},{"day":4,"hour":12,"count":6},{"day":4,"hour":13,"count":0},{"day":4,"hour":14,"count":0},{"day":4,"hour":15,"count":0},{"day":4,"hour":16,"count":0},{"day":4,"hour":17,"count":0},{"day":4,"hour":18,"count":0},{"day":4,"hour":19,"count":7},{"day":4,"hour":20,"count":9},{"day":4,"hour":21,"count":3},{"day":4,"hour":22,"count":5},{"day":4,"hour":23,"count":7},{"day":5,"hour":0,"count":7},{"day":5,"hour":1,"count":11},{"day":5,"hour":2,"count":10},{"day":5,"hour":3,"count":9},{"day":5,"hour":4,"count":3},{"day":5,"hour":5,"count":0},{"day":5,"hour":6,"count":3},{"day":5,"hour":7,"count":1},{"day":5,"hour":8,"count":0},{"day":5,"hour":9,"count":0},{"day":5,"hour":10,"count":0},{"day":5,"hour":11,"count":1},{"day":5,"hour":12,"count":10},{"day":5,"hour":13,"count":0},{"day":5,"hour":14,"count":0},{"day":5,"hour":15,"count":0},{"day":5,"hour":16,"count":0},{"day":5,"hour":17,"count":0},{"day":5,"hour":18,"count":0},{"day":5,"hour":19,"count":4},{"day":5,"hour":20,"count":7},{"day":5,"hour":21,"count":0},{"day":5,"hour":22,"count":0},{"day":5,"hour":23,"count":0},{"day":6,"hour":0,"count":5},{"day":6,"hour":1,"count":9},{"day":6,"hour":2,"count":2},{"day":6,"hour":3,"count":4},{"day":6,"hour":4,"count":0},{"day":6,"hour":5,"count":0},{"day":6,"hour":6,"count":0},{"day":6,"hour":7,"count":2},{"day":6,"hour":8,"count":0},{"day":6,"hour":9,"count":0},{"day":6,"hour":10,"count":1},{"day":6,"hour":11,"count":1},{"day":6,"hour":12,"count":0},{"day":6,"hour":13,"count":0},{"day":6,"hour":14,"count":0},{"day":6,"hour":15,"count":0},{"day":6,"hour":16,"count":0},{"day":6,"hour":17,"count":0},{"day":6,"hour":18,"count":0},{"day":6,"hour":19,"count":0},{"day":6,"hour":20,"count":0},{"day":6,"hour":21,"count":0},{"day":6,"hour":22,"count":0},{"day":6,"hour":23,"count":0},{"day":7,"hour":0,"count":0},{"day":7,"hour":1,"count":12},{"day":7,"hour":2,"count":8},{"day":7,"hour":3,"count":8},{"day":7,"hour":4,"count":3},{"day":7,"hour":5,"count":9},{"day":7,"hour":6,"count":1},{"day":7,"hour":7,"count":3},{"day":7,"hour":8,"count":2},{"day":7,"hour":9,"count":3},{"day":7,"hour":10,"count":0},{"day":7,"hour":11,"count":1},{"day":7,"hour":12,"count":7},{"day":7,"hour":13,"count":7},{"day":7,"hour":14,"count":0},{"day":7,"hour":15,"count":0},{"day":7,"hour":16,"count":0},{"day":7,"hour":17,"count":0},{"day":7,"hour":18,"count":0},{"day":7,"hour":19,"count":0},{"day":7,"hour":20,"count":0},{"day":7,"hour":21,"count":0},{"day":7,"hour":22,"count":3},{"day":7,"hour":23,"count":0},{"day":8,"hour":0,"count":2},{"day":8,"hour":1,"count":8},{"day":8,"hour":2,"count":13},{"day":8,"hour":3,"count":6},{"day":8,"hour":4,"count":4},{"day":8,"hour":5,"count":3},{"day":8,"hour":6,"count":0},{"day":8,"hour":7,"count":3},{"day":8,"hour":8,"count":11},{"day":8,"hour":9,"count":2},{"day":8,"hour":10,"count":5},{"day":8,"hour":11,"count":7},{"day":8,"hour":12,"count":1},{"day":8,"hour":13,"count":9},{"day":8,"hour":14,"count":0},{"day":8,"hour":15,"count":0},{"day":8,"hour":16,"count":0},{"day":8,"hour":17,"count":0},{"day":8,"hour":18,"count":0},{"day":8,"hour":19,"count":5},{"day":8,"hour":20,"count":0},{"day":8,"hour":21,"count":0},{"day":8,"hour":22,"count":12},{"day":8,"hour":23,"count":0},{"day":9,"hour":0,"count":7},{"day":9,"hour":1,"count":10},{"day":9,"hour":2,"count":3},{"day":9,"hour":3,"count":13},{"day":9,"hour":4,"count":7},{"day":9,"hour":5,"count":2},{"day":9,"hour":6,"count":0},{"day":9,"hour":7,"count":2},{"day":9,"hour":8,"count":4},{"day":9,"hour":9,"count":2},{"day":9,"hour":10,"count":3},{"day":9,"hour":11,"count":5},{"day":9,"hour":12,"count":4},{"day":9,"hour":13,"count":0},{"day":9,"hour":14,"count":0},{"day":9,"hour":15,"count":7},{"day":9,"hour":16,"count":0},{"day":9,"hour":17,"count":0},{"day":9,"hour":18,"count":10},{"day":9,"hour":19,"count":0},{"day":9,"hour":20,"count":0},{"day":9,"hour":21,"count":0},{"day":9,"hour":22,"count":0},{"day":9,"hour":23,"count":2},{"day":10,"hour":0,"count":10},{"day":10,"hour":1,"count":22},{"day":10,"hour":2,"count":15},{"day":10,"hour":3,"count":18},{"day":10,"hour":4,"count":5},{"day":10,"hour":5,"count":0},{"day":10,"hour":6,"count":4},{"day":10,"hour":7,"count":0},{"day":10,"hour":8,"count":3},{"day":10,"hour":9,"count":1},{"day":10,"hour":10,"count":13},{"day":10,"hour":11,"count":3},{"day":10,"hour":12,"count":5},{"day":10,"hour":13,"count":13},{"day":10,"hour":14,"count":0},{"day":10,"hour":15,"count":0},{"day":10,"hour":16,"count":0},{"day":10,"hour":17,"count":0},{"day":10,"hour":18,"count":0},{"day":10,"hour":19,"count":0},{"day":10,"hour":20,"count":0},{"day":10,"hour":21,"count":0},{"day":10,"hour":22,"count":2},{"day":10,"hour":23,"count":0},{"day":11,"hour":0,"count":5},{"day":11,"hour":1,"count":10},{"day":11,"hour":2,"count":15},{"day":11,"hour":3,"count":6},{"day":11,"hour":4,"count":2},{"day":11,"hour":5,"count":2},{"day":11,"hour":6,"count":0},{"day":11,"hour":7,"count":2},{"day":11,"hour":8,"count":2},{"day":11,"hour":9,"count":10},{"day":11,"hour":10,"count":6},{"day":11,"hour":11,"count":5},{"day":11,"hour":12,"count":12},{"day":11,"hour":13,"count":0},{"day":11,"hour":14,"count":0},{"day":11,"hour":15,"count":0},{"day":11,"hour":16,"count":0},{"day":11,"hour":17,"count":0},{"day":11,"hour":18,"count":0},{"day":11,"hour":19,"count":0},{"day":11,"hour":20,"count":0},{"day":11,"hour":21,"count":0},{"day":11,"hour":22,"count":8},{"day":11,"hour":23,"count":2},{"day":12,"hour":0,"count":0},{"day":12,"hour":1,"count":13},{"day":12,"hour":2,"count":17},{"day":12,"hour":3,"count":10},{"day":12,"hour":4,"count":0},{"day":12,"hour":5,"count":7},{"day":12,"hour":6,"count":4},{"day":12,"hour":7,"count":0},{"day":12,"hour":8,"count":0},{"day":12,"hour":9,"count":11},{"day":12,"hour":10,"count":1},{"day":12,"hour":11,"count":1},{"day":12,"hour":12,"count":0},{"day":12,"hour":13,"count":13},{"day":12,"hour":14,"count":19},{"day":12,"hour":15,"count":0},{"day":12,"hour":16,"count":0},{"day":12,"hour":17,"count":0},{"day":12,"hour":18,"count":0},{"day":12,"hour":19,"count":11},{"day":12,"hour":20,"count":14},{"day":12,"hour":21,"count":0},{"day":12,"hour":22,"count":0},{"day":12,"hour":23,"count":0}]
;
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<!-- D3.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
<!-- Google Font -->
<link href='http://fonts.googleapis.com/css?family=Open+Sans:300,400' rel='stylesheet' type='text/css'>
<script src="accidents.js"></script>
<style>
html { font-size: 62.5%; }
body {
font-size: 1rem;
font-family: 'Open Sans', sans-serif;
font-weight: 400;
fill: #8C8C8C;
text-align: center;
background-color: #000000;
}
.timeLabel, .dayLabel {
font-size: 1.6rem;
fill: #ffffff;
font-weight: 300;
}
text.axis-workweek, text.axis-worktime {
fill: #eaeaea;
font-weight: 400;
}
.title {
font-size: 2.8rem;
fill: #f9f9f9;
font-weight: 300;
}
.subtitle {
font-size: 1.4rem;
fill: #dddddd;
font-weight: 300;
}
.credit {
font-size: 1.2rem;
fill: #c1c1c1;
font-weight: 400;
}
.axis path, .axis tick, .axis line {
fill: none;
stroke: none;
}
text {
font-size: 1.2rem;
fill: #efefef;
font-weight: 400;
}
.legendTitle {
font-size: 1.6rem;
fill: #f9fff9;
font-weight: 300;
}
</style>
</head>
<body>
<div id="trafficAccidents"></div>
<script src="script.js"></script>
</script>
</body>
</html>
///////////////////////////////////////////////////////////////////////////
//////////////////// Set up and initiate svg containers ///////////////////
///////////////////////////////////////////////////////////////////////////
var days = ["1", "2", "3", "4", "5", "6", "7", "8","9","10","11","12"],
times = d3.range(24);
var margin = {
top: 170,
right: 50,
bottom: 70,
left: 50
};
var width = Math.max(Math.min(window.innerWidth, 1000), 500) - margin.left - margin.right - 20,
gridSize = Math.floor(width / times.length),
height = gridSize * (days.length+2);
//SVG container
var svg = d3.select('#trafficAccidents')
.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 + ")");
//Reset the overall font size
var newFontSize = width * 62.5 / 900;
d3.select("html").style("font-size", newFontSize + "%");
///////////////////////////////////////////////////////////////////////////
//////////////////////////// Draw Heatmap /////////////////////////////////
///////////////////////////////////////////////////////////////////////////
//Based on the heatmap example of: http://blockbuilder.org/milroc/7014412
var colorScale = d3.scale.linear()
.domain([0, d3.max(accidents, function(d) {return d.count; })/2, d3.max(accidents, function(d) {return d.count; })])
.range(["#ffefdb", "#ea6351", "#790905"])
//.interpolate(d3.interpolateHcl);
//.range(["#FFFFDD", "#3E9583", "#1F2D86"])
var dayLabels = svg.selectAll(".dayLabel")
.data(days)
.enter().append("text")
.text(function (d) { return d; })
.attr("x", 0)
.attr("y", function (d, i) { return i * gridSize; })
.style("text-anchor", "end")
.attr("transform", "translate(-6," + gridSize / 1.5 + ")")
.attr("class", function (d, i) { return ((i >= 0 && i <= 11) ? "dayLabel mono axis axis-workweek" : "dayLabel mono axis"); });
var timeLabels = svg.selectAll(".timeLabel")
.data(times)
.enter().append("text")
.text(function(d) { return d; })
.attr("x", function(d, i) { return i * gridSize; })
.attr("y", 0)
.style("text-anchor", "middle")
.attr("transform", "translate(" + gridSize / 2 + ", -6)")
.attr("class", function(d, i) { return ((i >= 0 && i <= 11) ? "timeLabel mono axis axis-worktime" : "timeLabel mono axis"); });
var heatMap = svg.selectAll(".hour")
.data(accidents)
.enter().append("rect")
.attr("x", function(d) { return (d.hour) * gridSize; })
.attr("y", function(d) { return (d.day - 1) * gridSize; })
.attr("class", "hour bordered")
.attr("width", gridSize)
.attr("height", gridSize)
.style("stroke", "#000")
.style("stroke-width", "2")
.style("stroke-opacity", 0.8)
.style("fill", function(d) { return colorScale(d.count); });
//Append title to the top
svg.append("text")
.attr("class", "title")
.attr("x", width/2)
.attr("y", -90)
.style("text-anchor", "middle")
.text("Eating and Drinking Over 24 hours");
svg.append("text")
.attr("class", "subtitle")
.attr("x", width/2)
.attr("y", -60)
.style("text-anchor", "middle")
.text("Data binned by hour");
//Append credit at bottom
svg.append("text")
.attr("class", "credit")
.attr("x", width/2)
.attr("y", gridSize * (days.length+1) + 70)
.style("text-anchor", "middle")
.text("Red line represents change from red to white light");
///////////////////////////////////////////////////////////////////////////
//////////////// Create the gradient for the legend ///////////////////////
///////////////////////////////////////////////////////////////////////////
//Extra scale since the color scale is interpolated
var countScale = d3.scale.linear()
.domain([0, d3.max(accidents, function(d) {return d.count; })])
.range([0, width])
//Calculate the variables for the temp gradient
var numStops = 10;
countRange = countScale.domain();
countRange[2] = countRange[1] - countRange[0];
countPoint = [];
for(var i = 0; i < numStops; i++) {
countPoint.push(i * countRange[2]/(numStops-1) + countRange[0]);
}//for i
//Create the gradient
svg.append("defs")
.append("linearGradient")
.attr("id", "legend-traffic")
.attr("x1", "0%").attr("y1", "0%")
.attr("x2", "100%").attr("y2", "0%")
.selectAll("stop")
.data(d3.range(numStops))
.enter().append("stop")
.attr("offset", function(d,i) {
return countScale( countPoint[i] )/width;
})
.attr("stop-color", function(d,i) {
return colorScale( countPoint[i] );
});
///////////////////////////////////////////////////////////////////////////
////////////////////////// Draw the legend ////////////////////////////////
///////////////////////////////////////////////////////////////////////////
var legendWidth = Math.min(width*0.8, 400);
//Color Legend container
var legendsvg = svg.append("g")
.attr("class", "legendWrapper")
.attr("transform", "translate(" + (width/2) + "," + (gridSize * days.length + 40) + ")");
//Draw the Rectangle
legendsvg.append("rect")
.attr("class", "legendRect")
.attr("x", -legendWidth/2)
.attr("y", 0)
//.attr("rx", hexRadius*1.25/2)
.attr("width", legendWidth)
.attr("height", 10)
.style("fill", "url(#legend-traffic)");
//Append title
legendsvg.append("text")
.attr("class", "legendTitle")
.attr("x", 0)
.attr("y", -10)
.style("text-anchor", "middle")
.text("Frequency of Eating/Drinking");
//Set scale for x-axis
var xScale = d3.scale.linear()
.range([-legendWidth/2, legendWidth/2])
.domain([ 0, d3.max(accidents, function(d) { return d.count; })] );
//Define x-axis
var xAxis = d3.svg.axis()
.orient("bottom")
.ticks(5)
//.tickFormat(formatPercent)
.scale(xScale);
//Set up X axis
legendsvg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + (10) + ")")
.call(xAxis);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment