|
<!DOCTYPE html> |
|
<meta charset="utf-8"> |
|
<style> |
|
|
|
.stroke { |
|
fill: none; |
|
stroke: #000; |
|
stroke-width: .5; |
|
} |
|
|
|
|
|
.node { |
|
stroke: #fff; |
|
stroke-width: 1.5px; |
|
} |
|
|
|
.link { |
|
stroke: #999; |
|
stroke-opacity: .6; |
|
} |
|
|
|
|
|
</style> |
|
<body> |
|
<script src="http://d3js.org/d3.v3.min.js"></script> |
|
<script src="http://d3js.org/d3.geo.tile.v0.min.js"></script> |
|
<script src="d3.mapzoom.js"></script> |
|
<script src="dijkstra.js"></script> |
|
<script> |
|
|
|
var width = 900, |
|
height = 600; |
|
|
|
var center = [-92.4, 36.8], scale = 816; |
|
|
|
var mapzoom = d3.mapzoom() |
|
.center(center) |
|
.scale(scale) |
|
|
|
var svg = d3.select("body").append("svg") |
|
.attr("width", width) |
|
.attr("height", height) |
|
.call(mapzoom); |
|
|
|
var frame = svg.append("g") |
|
|
|
|
|
mapzoom.addTileLayer(frame, "tiles.mapbox.com/v3/examples.map-zr0njcqy/", "abcd"); |
|
|
|
d3.tsv("places.tsv", function(cities) { |
|
d3.csv("distance.csv", function(edges) { |
|
main(cities, edges); |
|
}); |
|
}); |
|
|
|
function main(nodes, links) { |
|
|
|
var projection = mapzoom.projection(), |
|
nodesByName = {} |
|
|
|
nodes.forEach(function(d) { |
|
d.coord = [+d.lon, +d.lat] |
|
nodesByName[d.name] = d; |
|
d.links = []; |
|
}); |
|
|
|
links.forEach(function(d) { |
|
d.source = nodesByName[d.source] |
|
d.target = nodesByName[d.target] |
|
d.value = +d.value; |
|
}); |
|
|
|
var link = svg.append("g").selectAll(".link") |
|
.data(links) |
|
.enter().append("path") |
|
.attr("class", "link") |
|
.style("stroke-width", 1); |
|
|
|
var node = svg.append("g").selectAll(".node") |
|
.data(nodes) |
|
.enter().append("circle") |
|
.attr("class", "node") |
|
.attr("r", 5) |
|
.attr("fill", "grey") |
|
|
|
node |
|
.append("title") |
|
.text(function(d) { return d.name }) |
|
|
|
mapzoom.addLayer(function() { |
|
node |
|
.each(function(d) { d.proj = projection(d.coord); }) |
|
.attr("transform", function(d) { return "translate(" + d.proj + ")" }) |
|
link |
|
.attr("d", function(d) { return "M " + d.source.proj + " L " + d.target.proj }); |
|
|
|
}); |
|
|
|
link.each(function(d) { |
|
d.source.links.push(d); |
|
d.selection = d3.select(this); |
|
}); |
|
|
|
node.each(function(d) { |
|
d.selection = d3.select(this); |
|
}); |
|
|
|
|
|
node.append("title") |
|
.text(function(d) { return d.name; }); |
|
|
|
link.append("title") |
|
.text(function(d) { return d.source.name + " → " + d.target.name + "\n" + d.value + " mi" }); |
|
|
|
node.on("mouseover", function(d) { |
|
d3.select(this) |
|
.attr("r", 10) |
|
|
|
d.links.forEach(function(l) { |
|
l.selection |
|
.style("stroke-width", 10) |
|
l.target.selection |
|
.attr("r", 7); |
|
}); |
|
}); |
|
|
|
node.on("mouseout", function(d) { |
|
node.attr("r", 5) |
|
link.style("stroke-width", 1); |
|
}); |
|
|
|
link.on("mouseover", function(d) { |
|
d3.select(this) |
|
.style("stroke-width", 10); |
|
d.source.selection |
|
.attr("r", 10); |
|
d.target.selection |
|
.attr("r", 10); |
|
}); |
|
|
|
link.on("mouseout", function() { |
|
d3.select(this) |
|
.style("stroke-width", 1); |
|
node.attr("r", 5); |
|
}); |
|
|
|
var dijkstra = d3.dijkstra() |
|
.nodes(nodes) |
|
.edges(links); |
|
|
|
var color = d3.scale.linear() |
|
.domain([0, 1000, 2500]) |
|
.range(["green", "yellow", "red"]); |
|
|
|
dijkstra.on("tick", function() { |
|
node.style("fill", function(d) { return color(d.distance); }); |
|
}); |
|
|
|
dijkstra.on("end", function() { |
|
var name = dijkstra.source().name; |
|
node.select("title") |
|
.text(function(d) { return d.name + "\n(" + d.distance + " miles from " + name + ")" }); |
|
}); |
|
|
|
node.on("click", dijkstra.start); |
|
|
|
} |
|
|
|
|
|
</script> |
|
|