|
<!DOCTYPE html> |
|
<meta charset="utf-8"> |
|
<style> |
|
|
|
body { |
|
background: #fcfcfa; |
|
} |
|
|
|
.stroke { |
|
fill: none; |
|
stroke: #999; |
|
stroke-width: 3px; |
|
} |
|
|
|
.fill { |
|
fill: #fff; |
|
} |
|
|
|
.graticule { |
|
fill: none; |
|
stroke: #ddd; |
|
stroke-width: .5px; |
|
stroke-opacity: .5; |
|
} |
|
|
|
.land { |
|
fill: #ddd; |
|
} |
|
|
|
.boundary { |
|
fill: none; |
|
stroke: #fff; |
|
stroke-width: .5px; |
|
} |
|
|
|
.points circle { |
|
fill: #fff; |
|
stroke: red; |
|
stroke-width: 2px; |
|
} |
|
|
|
.points text { |
|
font: 11px sans-serif; |
|
text-anchor: middle; |
|
text-shadow: 0 1px 0 #fff, 0 -1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff; |
|
} |
|
|
|
.route { |
|
fill: none; |
|
stroke: red; |
|
stroke-width: 3px; |
|
} |
|
|
|
.possible-route { |
|
stroke-dasharray:5, 5; |
|
fill: none; |
|
stroke: red; |
|
stroke-width: 3px; |
|
} |
|
|
|
.arrowHead{ |
|
fill:red; |
|
} |
|
</style> |
|
<body> |
|
<script src="http://d3js.org/d3.v3.min.js"></script> |
|
<script src="http://d3js.org/d3.geo.projection.v0.min.js"></script> |
|
<script src="http://d3js.org/topojson.v1.min.js"></script> |
|
<script> |
|
|
|
var width = 960, |
|
height = 570; |
|
|
|
var places = { |
|
HNL: [-157 - 55 / 60 - 21 / 3600, 21 + 19 / 60 + 07 / 3600], |
|
HKG: [113 + 54 / 60 + 53 / 3600, 22 + 18 / 60 + 32 / 3600], |
|
SVO: [37 + 24 / 60 + 53 / 3600, 55 + 58 / 60 + 22 / 3600], |
|
HAV: [-82 - 24 / 60 - 33 / 3600, 22 + 59 / 60 + 21 / 3600], |
|
CCS: [-66 - 59 / 60 - 26 / 3600, 10 + 36 / 60 + 11 / 3600], |
|
UIO: [-78 - 21 / 60 - 31 / 3600, 0 + 06 / 60 + 48 / 3600] |
|
}; |
|
|
|
|
|
var routes = { |
|
known:[ |
|
[ places.HNL, places.HKG ], |
|
[ places.HKG, places.SVO ] |
|
], |
|
possible:[ |
|
[ places.SVO, places.HAV ], |
|
[ places.HAV, places.CCS ], |
|
[ places.CCS, places.UIO ] |
|
] |
|
}; |
|
|
|
var projection = d3.geo.kavrayskiy7() |
|
.scale(170) |
|
.rotate([-40, 0]) |
|
.translate([width / 2, height / 2]) |
|
.precision(.1); |
|
|
|
var path = d3.geo.path() |
|
.projection(projection); |
|
|
|
var graticule = d3.geo.graticule(); |
|
|
|
var svg = d3.select("body").append("svg") |
|
.attr("width", width) |
|
.attr("height", height); |
|
|
|
svg.append("defs").append("path") |
|
.datum({type: "Sphere"}) |
|
.attr("id", "sphere") |
|
.attr("d", path); |
|
|
|
d3.select("defs") |
|
.append("marker") |
|
.attr("id", "arrow") |
|
.attr("viewBox", "0 -5 10 10") |
|
.attr("refX", 15) |
|
.attr("refY", 0) |
|
.attr("markerWidth", 4) |
|
.attr("markerHeight", 4) |
|
.attr("orient", "auto") |
|
.append("path") |
|
.attr("d", "M0,-5L10,0L0,5") |
|
.attr("class","arrowHead"); |
|
|
|
|
|
svg.append("use") |
|
.attr("class", "stroke") |
|
.attr("xlink:href", "#sphere"); |
|
|
|
svg.append("use") |
|
.attr("class", "fill") |
|
.attr("xlink:href", "#sphere"); |
|
|
|
svg.append("path") |
|
.datum(graticule) |
|
.attr("class", "graticule") |
|
.attr("d", path); |
|
|
|
for(var i=0;i<routes.known.length;i++){ |
|
svg.append("path") |
|
.datum({ |
|
type:"LineString", |
|
coordinates:routes.known[i] |
|
}) |
|
.attr("class", "route") |
|
.attr("d", path) |
|
.attr("marker-end", "url(#arrow)"); |
|
} |
|
|
|
for(var i=0;i<routes.possible.length;i++){ |
|
svg.append("path") |
|
.datum({ |
|
type:"LineString", |
|
coordinates:routes.possible[i] |
|
}) |
|
.attr("class", "possible-route") |
|
.attr("d", path) |
|
.attr("marker-end", "url(#arrow)"); |
|
} |
|
|
|
var point = svg.append("g") |
|
.attr("class", "points") |
|
.selectAll("g") |
|
.data(d3.entries(places)) |
|
.enter().append("g") |
|
.attr("transform", function(d) { return "translate(" + projection(d.value) + ")"; }); |
|
|
|
point.append("circle") |
|
.attr("r", 4.5); |
|
|
|
point.append("text") |
|
.attr("y", 10) |
|
.attr("dy", ".71em") |
|
.text(function( d ) { return d.key; }); |
|
|
|
d3.json("/mbostock/raw/4090846/world-50m.json", function(error, world) { |
|
svg.insert("path", ".graticule") |
|
.datum(topojson.feature(world, world.objects.land)) |
|
.attr("class", "land") |
|
.attr("d", path); |
|
|
|
svg.insert("path", ".graticule") |
|
.datum(topojson.mesh(world, world.objects.countries, function(a, b) { return a !== b; })) |
|
.attr("class", "boundary") |
|
.attr("d", path); |
|
}); |
|
|
|
d3.select(self.frameElement).style("height", height + "px"); |
|
|
|
</script> |