Skip to content

Instantly share code, notes, and snippets.

@Andrew-Reid
Last active January 11, 2023 14:09
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Andrew-Reid/8de4b9d0d0a87a478770e0cc86e2f5e4 to your computer and use it in GitHub Desktop.
Save Andrew-Reid/8de4b9d0d0a87a478770e0cc86e2f5e4 to your computer and use it in GitHub Desktop.
Flow Map

This is an attempt at a flow chart using d3.js v4. It simply scales each path's width according to a given variable. It is based off one of Mike Bostock's v3 maps. My code could be shorter, but I find this clear. Click "Open" above to see the whole map.

The map shows lumber exports from the Puget Sound region. The data are from 1882-3 (July to July, incomplete data, 8 months worth I beleive) based on exports reported in the Puget Sound Weekly Argus. Each path's width is porportional with the board feed of lumber exported to a particular destination. While predominately focused on Puget Sound, the paper occasionally included Burrard Inlet, which has also been included. Over 60 million board feet are recorded in this dataset.

I'm hoping to work on a revision that improves upon this layout to make it more clear (avoiding overlap) and to change the format of the origin point to a stacked line, time permitting.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html lang="en">
<head>
<script src="http://d3js.org/d3.v4.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/topojson/1.6.19/topojson.min.js"></script>
<script src="https://d3js.org/d3-geo-projection.v1.min.js"></script>
<style>
.route {
fill: none;
stroke: #333;
opacity: 0.5;
}
.land { fill:#a8ddb5; }
svg { background: #43a2ca; }
.source-port {
fill: white;
stroke: darkgreen;
stroke-width: 2px;
}
</style>
</head>
<body>
<div id="map"> </div>
<script>
var width = 950; var height = 650;
var projection = d3.geoKavrayskiy7()
.scale(302)
.rotate([-210,-10])
.translate([width/2,height/2])
.precision(0.1);
var path = d3.geoPath().projection(projection);
var svg = d3.select("#map").append("svg")
.attr("width", width)
.attr("height", height);
// Create a few groups to layer elements correctly
var g1 = svg.append("g");
var g2 = svg.append("g");
d3.json("world.json",function(error,world) {
g1.insert("path")
.datum(topojson.feature(world, world.objects.land))
.attr("class", "land")
.attr("d", path);
g2.append("circle")
.attr("cx", function() { return projection(ports["Puget Sound"].loc)[0];})
.attr("cy", function() { return projection(ports["Puget Sound"].loc)[1];})
.attr("r",6)
.attr("class","source-port");
g2.append("text")
.attr("x", function() { return projection(ports["Puget Sound"].loc)[0] + 5;})
.attr("y", function() { return projection(ports["Puget Sound"].loc)[1] + 0;})
.text("Puget Sound");
drawTrade();
});
// Draw a set of routes
function drawTrade() {
d3.csv("lumber.csv", function (error, routes) {
var maxVolume = d3.max(routes, function(d) { return d.vol; });
routePath = g1.selectAll(".route")
.data(routes)
.enter()
.append("path")
.attr("class","route")
.style("stroke-width", function(d) {
return 50 * d.vol;
})
.attr('d', function(d) {
return path ({
type:"LineString",
coordinates: [ ports["Puget Sound"].loc,ports[d.destination].loc ]
});
})
portMarkers = g1.selectAll(".ports")
.data(routes)
.enter()
.append("circle")
.attr("class","ports")
.attr("cx", function(d) { return projection(ports[d.destination].loc)[0] } )
.attr("cy", function(d) { return projection(ports[d.destination].loc)[1] } )
.attr("r", function(d) { return d.vol * 25 })
.style("fill","white")
.style("stroke-width",2)
.style("stroke","red");
portLabels = g2.selectAll(".port-labels")
.data(routes)
.enter()
.append("text")
.attr("x", function(d) { return projection(ports[d.destination].loc)[0] + ports[d.destination].off[0] } )
.attr("y", function(d) { return projection(ports[d.destination].loc)[1] - ports[d.destination].off[1] } )
.text(function(d) { return d.destination })
.attr("class","port-label");
});
}
// Ports reference and text offset for labels.
var ports = {
Honolulu:{loc:[-157.816667,21.3],off:[-67,0]},
"Puget Sound":{loc:[-123.365556,48.428611],off:[5,5]},
Sydney:{loc:[151.209444,-33.859972],off:[10,-5]},
Yokohama:{loc:[139.653905,35.455161],off:[-25,-15]},
"Hong Kong":{loc:[114.204277,22.330869],off:[-50,11]},
Callao:{loc:[-77.131981,-11.876547],off:[10,5]},
Shanghai:{loc:[121.475449,31.230331],off:[-60,7]},
Melbourne:{loc:[144.96668,-37.812339],off:[-75,-3]},
Valparaiso:{loc:[-71.616667,-33.05],off:[6,-5]},
Iquique:{loc:[-70.15,-20.216667],off:[8,-4]},
Coquimbo:{loc:[-71.345873,-29.949609],off:[2,7]},
Tahiti:{loc:[-149.561182,-17.538858],off:[10,0]},
Guaymas:{loc:[-110.900017,27.920381],off:[-70,0]},
Adelaide:{loc:[138.601,-34.929],off:[-60,-3] },
Noumea: {loc:[166.466667,-22.266667],off:[10,-5] },
Antofagasto: {loc:[-70.4,-23.65],off:[10,0] },
Fiji: {loc: [178.45,-18.166667],off:[10,0] }
};
</script>
</body>
</html>
destination vol
Valparaiso 0.246
Sydney 0.139
Honolulu 0.135
Melbourne 0.109
Shanghai 0.098
Iquique 0.061
Callao 0.049
Guaymas 0.035
Adelaide 0.03378
Coquimbo 0.019042
Noumea 0.015
Fiji 0.010
Yokohama 0.009
Antofagasto 0.008
Tahiti 0.007
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment