Skip to content

Instantly share code, notes, and snippets.

@venkat
Last active June 29, 2017 23:21
Show Gist options
  • Save venkat/fc18d44d56dac4ca08fdce1b57366397 to your computer and use it in GitHub Desktop.
Save venkat/fc18d44d56dac4ca08fdce1b57366397 to your computer and use it in GitHub Desktop.
A continuous simulation of items being shipped in the US
license: gpl-3.0
height: 600
border: no

This D3 US map shows a non-stop animatation of route that helps visualize an item being shipped between two locations.

It randomly picks zipcode locations to create routes between them.

Based off of my previous animation which shows the animation for a single route - https://bl.ocks.org/venkat/e7b6e498ba87a2a6b7423ca7525773d6

<!DOCTYPE html>
<style>
.states :hover {
fill: red;
}
.state-borders {
fill: none;
stroke: #fff;
stroke-width: 0.5px;
stroke-linejoin: round;
stroke-linecap: round;
pointer-events: none;
}
</style>
<svg width="960" height="600"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<script>
//Width and height of map
var width = 960;
var height = 500;
var svg = d3.select("svg");
var projection = d3.geoAlbersUsa()
.translate([width/2, height/2]) // translate to center of screen
.scale([1000]); // scale things down so see entire US
var path = d3.geoPath(projection);
function uniqueId() {
return Math.random().toString(36).substr(2, 36) + new Date().getUTCMilliseconds()
}
//initializing with some sample points
var origin = [-122.336422, 47.610902];
var destination = [-73.986740, 40.662688];
var origin1 = [-87.981494, 41.745663];
var destination1= [-74.591878, 40.061957];
var routePairs = [
{id: uniqueId(), type: "LineString", coordinates: [origin, destination]},
{id: uniqueId(), type: "LineString", coordinates: [origin1, destination1]}
];
//keeping track of routes that done animating to remove them
var animatedRoutes = {};
//the size of the routePairs array to keep it from growing indefinitely
var maxRoutes = 50;
//limites the size of the routePairs array so routes done animating are removed
function trim(routePairs, animatedRoutes, maxRoutes) {
while(routePairs.length > maxRoutes) {
if (!(routePairs[0].id in animatedRoutes)) {
break;
}
delete animatedRoutes[routePairs[0].id];
routePairs.shift();
}
}
function drawStates(us) {
svg.append("g")
.attr("class", "states")
.selectAll("path")
.data(topojson.feature(us, us.objects.states).features)
.enter().append("path")
.attr("d", path);
svg.append("path")
.attr("class", "state-borders")
.attr("d", path(topojson.mesh(us, us.objects.states, function(a, b) { return a !== b; })));
}
function animateRoutes(routePairs) {
var routes = svg.selectAll(".route")
.data(routePairs, function(d) { return d.id; })
routes.exit().remove();
routes.enter()
.append("path")
.attr("class", "route")
.attr("id", function(d) { return d.id; })
.attr("d", path)
.attr("stroke", "#d3d3d3")
.attr("fill", "none")
.attr("stroke-dasharray", function(){
var t = this.getTotalLength();
this.__data__["len"] = t;
return t + "," + t;
})
.attr("stroke-dashoffset", function(){return this.__data__.len; })
.transition()
.duration(300)
.ease(d3.easeCubic)
.attr("stroke-dashoffset", function(){return this.__data__.len * 2; })
.transition()
.duration(300)
.attr("stroke-dashoffset", function(){return this.__data__.len * 3; })
.on("end", function(d) {animatedRoutes[d.id] = null; } );
}
//randomly select zipcodes to simulate a route between them
function simulateNewData(routePairs, zipcodesLatLng) {
var zipcodes = Object.keys(zipcodesLatLng);
var zipcode1 = zipcodes[Math.floor(Math.random() * zipcodes.length)];
var zipcode2 = zipcodes[Math.floor(Math.random() * zipcodes.length)];
coordinates = [zipcodesLatLng[zipcode1], zipcodesLatLng[zipcode2]];
routePairs.push({id: uniqueId(), type: "LineString",
coordinates: coordinates
});
}
var zipcodesLatLng = d3.json("zipcodes.json", function(error, zipcodesLatLng){
if (error) throw error;
d3.interval(function(elapsed) {
simulateNewData(routePairs, zipcodesLatLng);
simulateNewData(routePairs, zipcodesLatLng);
animateRoutes(routePairs);
trim(routePairs, animatedRoutes, maxRoutes);
}, 200);
});
var us = d3.json("us-states.json", function(error, us) {
if (error) throw error;
drawStates(us);
animateRoutes(routePairs);
});
</script>
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file has been truncated, but you can view the full file.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment