Skeletal demo for d3.geoVoronoi
by Philippe Rivière.
forked from Fil's block: geoVoronoi Delaunay links and Urquhart graph
license: mit |
Skeletal demo for d3.geoVoronoi
by Philippe Rivière.
forked from Fil's block: geoVoronoi Delaunay links and Urquhart graph
<!DOCTYPE html> | |
<meta charset="utf-8"> | |
<style> | |
#sphere { | |
fill: #fff; | |
stroke: #444; | |
stroke-width: 2; | |
} | |
.polygons { | |
stroke: #444; | |
} | |
.links { | |
stroke: #aaa; | |
stroke-width: 0.5; | |
fill: none; | |
} | |
.links .secondary { | |
stroke-width: .5; | |
stroke-dasharray: 3 1; | |
} | |
.sites { | |
stroke: black; | |
fill: white; | |
} | |
#legend { | |
position: absolute; | |
top: 15; | |
left: 15; | |
font-family: sans-serif; | |
} | |
.countries { | |
fill: #999; | |
opacity: 0.3; | |
} | |
text { | |
/*fill: white;*/ | |
font-family: sans-serif; | |
font-size: 12px; | |
} | |
</style> | |
<div id="legend"> | |
GeoVoronoi des feuilles de l'Atlas uniforme | |
</div> | |
<svg width="960" height="600"></svg> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<script src="https://unpkg.com/d3-geo-voronoi@0"></script> | |
<script src="https://d3js.org/topojson.v1.min.js"></script> | |
<script> | |
feuilles = [ | |
[1, "Arctide … Pôle Nord", 0,90, -90 + 25], // rotation de maniere a avoir le golfe de Botnie à droite | |
[2, "Europe", 20,54], | |
[3, "Oural et Yenissei", 90, 61], | |
[4, "Amour et Lena", 141, 57], | |
[5, "Alaska", -161, 57], | |
[6, "Mackenzie et Hudson", -98, 61], | |
[7, "Atlantique boréal", -39, 57], | |
[8, "Méditerranée et Sahara", 12, 32], | |
[9, "Caspienne", 58, 40], | |
[10, "Euphrate et Gange", 65, 24], | |
[11, "Chine", 113, 27], | |
[12, "Japon", 160, 29], | |
[13, "Hawaï", -146, 29], | |
[14, "Mississippi et Saint-Laurent", -94, 35], | |
[15, "Antilles", -80, 20], | |
[16, "Atlantique, de Lisbonne à la Trinidad", -40, 29], | |
[17, "Nil", 29, 13], | |
[18, "Océan Indien Asiatique", 70, 7], | |
[19, "Insulasie", 118, 1], | |
[20, "Mélanésie", 160, 0], | |
[21, "Polynésie", -152, 0], | |
[22, "Galapagos", -104, 0], | |
[23, "Amazone", -59, 0], | |
[24, "Atlantique équatorial", -14, 0], | |
[25, "Zambèze et Cap", 33, -20], | |
[26, "Océan Indien, de Maurice à Perth", 84, -24], | |
[27, "Australie", 134, -26], | |
[28, "Nouvelle Zélande", 178, -30], | |
[29, "Pomotou", -123, -24], | |
[30, "Paraná", -68, -24], | |
[31, "Atlantique, de Rio au Cap", -17, -24], | |
[32, "Kerguelen, Enderby", 48, -55], | |
[33, "Océan Indien Austral", 108, -55], | |
[34, "Antipodes", 168, -55], | |
[35, "Pacifique Austral", -132, -55], | |
[36, "Cap Horn", -72, -55], | |
[37, "Atlantique austral", -12, -55], | |
[38, "Pôle Sud", 0, -88.7, 90 - 102], | |
// idem pole nord, sur l'angle 102° (-78° si on préfère retourner) | |
// ajout petit décalage Philippe Rivière à -88.5° pour avoir toute la masse continentale | |
] | |
var points = { | |
type: "FeatureCollection", | |
features: feuilles.map(d => { | |
return { | |
type: "Point", | |
coordinates: [ d[2], d[3] ], | |
properties: { name: `${d[0]}. ${d[1]}` } | |
} | |
}) | |
} | |
var v = d3.geoVoronoi()(points); | |
var projection = d3.geoEquirectangular().rotate([-175,0]), //d3.geoOrthographic(), | |
path = d3.geoPath().projection(projection); | |
var svg = d3.select("svg"); | |
svg.append('path') | |
.attr('id', 'sphere') | |
.datum({ type: "Sphere" }) | |
.attr('d', path); | |
svg.append('g') | |
.attr('class', 'polygons') | |
.selectAll('path') | |
.data(v.polygons().features) | |
.enter() | |
.append('path') | |
.attr('d', path) | |
.attr('fill', function(_,i) { return d3.schemeCategory10[i%10]; }) | |
.attr('fill-opacity', 0.3) | |
.append('title').text((d,i) => `${feuilles[i][0]}. ${feuilles[i][1]}`); | |
countries = svg.append('g') | |
.attr('class', 'countries') | |
svg.append('g') | |
.attr('class', 'links') | |
.selectAll('path') | |
.data(v.links().features) | |
.enter() | |
.append('path') | |
.classed('secondary', function(d) { | |
return !d.properties.urquhart; | |
}) | |
.attr('d', path); | |
svg.append('g') | |
.attr('class', 'sites') | |
.selectAll('path') | |
.data(points.features) | |
.enter() | |
.append('path') | |
.attr('d', path); | |
svg.append('g') | |
.attr('class', 'labels') | |
.selectAll('text') | |
.data(points.features) | |
.enter() | |
.append('text') | |
.attr('text-anchor', 'middle') | |
.attr('x', d => Math.max(70,projection(d.coordinates)[0])) | |
.attr('y', d => Math.max(45,projection(d.coordinates)[1]-8)) | |
.text(d => d.properties.name.length > 23 ? d.properties.name.substring(0,18)+'…' : d.properties.name) | |
; | |
// gentle animation | |
if (false) | |
d3.interval(function(elapsed) { | |
projection.rotate([ elapsed / 150, 0 ]); | |
svg.selectAll('path') | |
.attr('d', path); | |
}, 50); | |
d3.queue() | |
.defer(d3.json, 'countries.topo.json') | |
.await(function (err, wjson) { | |
countries | |
.selectAll('path') | |
.data(topojson.feature(wjson, wjson.objects.countries).features) | |
.enter() | |
.append('path') | |
.attr('d', path); | |
}); | |
</script> |