An implementation of a realtime event map, seen here: http://square.github.com/cube/
You can obtain states.json from the D3 website.
An implementation of a realtime event map, seen here: http://square.github.com/cube/
You can obtain states.json from the D3 website.
var options = require("./evaluator-config"), | |
cube = require("cube"), | |
server = cube.server(options); | |
server.register = function(db, endpoints) { | |
cube.evaluator.register(db, endpoints); | |
cube.visualizer.register(db, endpoints); | |
endpoints.http.push(cube.endpoint.exact("/us/map", cube.endpoint.file("static/us/map.html"))); | |
endpoints.http.push(cube.endpoint.exact("/us/states.json", cube.endpoint.file("static/us/states.json"))); | |
}; | |
server.start(); |
<!DOCTYPE html> | |
<script src="/d3/d3.js?2.7.1"></script> | |
<style> | |
body { | |
margin: 0 auto 0 auto; | |
width: 1920px; | |
} | |
svg, canvas { | |
position: absolute; | |
} | |
path { | |
fill: none; | |
stroke: #ccc; | |
} | |
</style> | |
<svg width="1920" height="1080"></svg> | |
<canvas width="1920" height="1080"></canvas> | |
<script> | |
var canvas = d3.select("canvas"), | |
w = +canvas.attr("width"), | |
h = +canvas.attr("height"); | |
var duration = 1000 * 60 * 30, // 30 minutes | |
start = new Date(Date.now() - duration), | |
utc = d3.time.format.iso; | |
var socket = new WebSocket("ws://localhost:1081/1.0/event/get"), | |
events = []; // cache of visible events | |
var context = canvas.node().getContext("2d"), | |
image = context.createImageData(w, h); | |
var projection = d3.geo.albersUsa() | |
.scale(2000) | |
.translate([w / 2, h / 2]); | |
// Save as on alt-click. | |
canvas.on("click", function() { | |
if (d3.event.altKey) window.open(this.toDataURL()); | |
}); | |
// Display the states in the background. | |
d3.json("/us/states.json", function(collection) { | |
d3.select("svg").selectAll("path") | |
.data(collection.features) | |
.enter().append("path") | |
.attr("d", d3.geo.path() | |
.projection(projection)); | |
}); | |
// On open, send the event request. Here, a generic event type called "event". | |
socket.onopen = function() { | |
socket.send(JSON.stringify({ | |
expression: "event(location)", | |
start: utc(start) | |
})); | |
}; | |
// On message, record the event. | |
socket.onmessage = function(message) { | |
var d = JSON.parse(message.data), | |
l = d.data.location, | |
p = projection(l), | |
x = Math.max(0, Math.min(w - 1, Math.round(p[0]))), | |
y = Math.max(0, Math.min(h - 1, Math.round(p[1]))), | |
i = w * y + x, | |
j = i << 2; | |
d.time = new Date(d.time); | |
d.next = events[i]; | |
events[i] = d; | |
image.data[j + 3] = 255; | |
d3.timer(draw); | |
}; | |
// Expire old events. | |
setInterval(function() { | |
var i = -1, | |
n = w * h, | |
o, | |
j, | |
expire = new Date(Date.now() - duration); | |
while (++i < n) { | |
if ((o = events[i]) && (o.time < expire)) { | |
image.data[(i << 2) + 3] = 0; | |
events[i] = null; | |
d3.timer(draw); | |
} | |
} | |
}, 5000); | |
function draw() { | |
context.putImageData(image, 0, 0); | |
return true; | |
} | |
</script> |