Skip to content

Instantly share code, notes, and snippets.

@irjudson
Created April 12, 2016 14:06
Show Gist options
  • Save irjudson/53b44de27b8f8f294df7616b9fa709c4 to your computer and use it in GitHub Desktop.
Save irjudson/53b44de27b8f8f294df7616b9fa709c4 to your computer and use it in GitHub Desktop.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>ThingLabs</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
<style>
body {
padding: 50px;
font: 10px sans-serif;
font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}
a {
color: #00B7FF;
}
svg {
font: 10px sans-serif;
}
.graph .axis {
stroke-width: 1;
}
.graph .axis .tick line {
stroke: black;
}
.graph .axis .tick text {
fill: black;
font-size: 0.7em;
}
.graph .axis .domain {
fill: none;
stroke: black;
}
.graph .group {
fill: none;
stroke: black;
stroke-width: 1.5;
}
#wrapper {
padding-left:312px;
position:relative;
}
#userList {
margin:0 0 30px 0;
}
#userList table {
border-collapse:separate;
border-spacing:1px;
background:#CCC;
}
#userList table th {
background:#EEE;
font-weight:600;
padding:10px 20px;
text-align:center;
}
#userList table tbody {
padding:0; margin:0;
border-collapse:collapse;
border-spacing:0px;
}
#userList table td {
background:#FFF;
padding:5px 10px;
text-align:center;
}
#userInfo {
width:250px;
position:absolute;
top:0; left:0;
}
#userInfo p {
padding:15px;
border:1px solid #CCC;
background:rgba(80,120,255,0.05);
}
fieldset {
border:0;
padding:0; margin:0;
}
</style>
<script src="/socket.io/socket.io.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script>
</head>
<body data-spy="scroll" data-target=".scrollspy">
<nav role="navigation" class="navbar navbar-inverse">
<div class="navbar-header">
<button type="button" data-toggle="collapse" data-target="#dropdown_menu" aria-expanded="false" aria-controls="navbar"
class="navbar-toggle collapsed"><span class="sr-only">Toggle navigation</span><span class="icon-bar"></span><span class="icon-bar"></span>
<span
class="icon-bar"></span>
</button><a class="navbar-brand">ThingLabs</a></div>
<div id="dropdown_menu" class="collapse navbar-collapse">
<ul class="nav navbar-nav"></ul>
</div>
</nav>
<div class="container">
<p>Welcome to ThingLabs</p>
<div class="graph"></div>
</div>
<script>
// Variables
var duration = 1000,
timeWindow = 5000,
width = 500,
height = 200,
now = new Date(Date.now() - timeWindow),
line = null,
io = io.connect(),
last = new Date(),
limit = 60 * 1,
groups = {
max: {
value: 0,
color: 'red',
data: new Array(limit).join('0').split('').map(parseFloat)
},
avg: {
value: 0,
color: 'green',
data: new Array(limit).join('0').split('').map(parseFloat)
},
min: {
value: 0,
color: 'blue',
data: new Array(limit).join('0').split('').map(parseFloat)
}
};
// Listen for session event.
io.emit('ready');
var x = d3.time.scale()
.domain([now - (limit - 2), now - timeWindow])
.range([0, width])
var y = d3.scale.linear()
.domain([0, 100])
.range([height, 0])
line = d3.svg.line()
.interpolate('basis')
.x(function(d, i) {
return x(now - (limit - 1 - i) * timeWindow)
})
.y(function(d) {
return y(d)
})
io.on('data', function(data) {
console.log("Got data: " + JSON.stringify(data, null, 2));
groups['max'].data.push(data['maxtempf']);
groups['avg'].data.push(data['avgtempf']);
groups['min'].data.push(data['mintempf']);
last = new Date();
});
var svg = d3.select('.graph').append('svg')
.attr('class', 'chart')
.attr('width', width)
.attr('height', height + 50)
var axis = svg.append('g')
.attr('class', 'x axis')
.attr('transform', 'translate(0,' + height + ')')
.call(x.axis = d3.svg.axis().scale(x).orient('bottom'))
var paths = svg.append('g')
for (var name in groups) {
var group = groups[name]
group.path = paths.append('path')
.data([group.data])
.attr('class', name + ' group')
.style('stroke', group.color)
}
// Update everything every tick
function tick() {
var now = new Date();
// Console update
console.log("Firing tick() at: " + now.toString());
// Add new values
for (var name in groups) {
var group = groups[name]
group.path.attr('d', line)
}
// Shift domain
x.domain([now - (limit - 2) * timeWindow, now - timeWindow])
// Slide x-axis left
axis.transition()
.duration(duration)
.ease('linear')
.call(x.axis)
// Slide paths left
paths.attr('transform', null)
.transition()
.duration(duration)
.ease('linear')
.attr('transform', 'translate(' + x(now - (limit - 1) * timeWindow) + ')')
.each('end', tick)
// Drop old data
if(groups['max'].data.length > 60) {
groups['max'].data.shift();
groups['avg'].data.shift();
groups['min'].data.shift();
}
}
tick();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment