|
<head> |
|
<script src="//cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.min.js"></script> |
|
<script src="//cdnjs.cloudflare.com/ajax/libs/topojson/3.0.2/topojson.min.js"></script> |
|
<script src="//cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.5/dat.gui.js"></script> |
|
<script src="//unpkg.com/d3-geo-voronoi@0"></script> |
|
<script src="//unpkg.com/d3-geo-zoom"></script> |
|
<script src="https://unpkg.com/versor"></script> |
|
<script src="https://unpkg.com/d3-inertia"></script> |
|
|
|
<style> |
|
body { margin: 0 } |
|
|
|
.sphere { |
|
fill: aqua; |
|
fill-opacity: 0.04; |
|
} |
|
|
|
.land { |
|
fill: darkgrey; |
|
fill-opacity: 0.2; |
|
} |
|
|
|
.graticule { |
|
stroke: black; |
|
stroke-width: 0.1; |
|
stroke-opacity: 0.3; |
|
fill: none; |
|
} |
|
|
|
.tec { |
|
fill: none; |
|
stroke: #999; |
|
stroke-width: 0.2; |
|
} |
|
.voronoi { |
|
fill: red; |
|
fill-opacity: 0; |
|
stroke: black; |
|
stroke-width: 0.2; |
|
stroke-opacity: 0.5; |
|
} |
|
|
|
.voronoi:hover { |
|
fill-opacity: 0.1; |
|
} |
|
|
|
.urquhart { |
|
stroke: maroon; |
|
stroke-width: 0.4; |
|
stroke-opacity: 0.7; |
|
fill: none; |
|
} |
|
|
|
.volcanoes { |
|
stroke: none; |
|
fill: maroon; |
|
pointer-events: none; |
|
} |
|
</style> |
|
</head> |
|
|
|
<body> |
|
<div id="world"></div> |
|
|
|
<script> |
|
// Controls |
|
const gui = new dat.GUI(); |
|
const controls = { 'Volcanoes': true, 'Graticule Grid': true, 'Voronoi Layer': false, 'Urquhart Layer': true , 'Max dist.': 0.1}; |
|
for (a in controls) |
|
gui.add(controls, a).onChange(_ => render()); |
|
|
|
const width = window.innerWidth; |
|
const height = window.innerHeight; |
|
|
|
const svg = d3.select('#world').append('svg') |
|
.attr('width', width) |
|
.attr('height', height); |
|
|
|
const projection = d3.geoOrthographic() |
|
.scale((height - 10) / 2) |
|
.translate([width / 2, height / 2]) |
|
.rotate([0, -35, 0]) |
|
.precision(0.1); |
|
|
|
const path = d3.geoPath() |
|
.projection(projection) |
|
.pointRadius(1.4); |
|
|
|
if (false) d3.geoZoom() |
|
.projection(projection) |
|
.onMove(render) |
|
(svg.node()); |
|
|
|
d3.queue() |
|
.defer(d3.json, 'https://unpkg.com/world-atlas@1/world/110m.json') |
|
.defer(d3.json, 'world_volcanoes.json') |
|
.defer(d3.json, "https://gistcdn.githack.com/benelsen/4969007/raw/d469915bf4b7441f6e2396336bfc4d63ed123d2f/tectonics.json") |
|
.awaitAll((error, [world, volcanoes, tec]) => { |
|
if (error) throw error; |
|
|
|
// water |
|
svg.append('path').attr('class', 'geo sphere') |
|
.datum({ type: 'Sphere' }); |
|
|
|
// land |
|
svg.append('path').attr('class', 'geo land') |
|
.datum(topojson.feature(world, world.objects.land).features[0]); |
|
console.log(tec) |
|
// tec |
|
svg.append('g') |
|
.selectAll('path') |
|
.data(topojson.feature(tec, tec.objects.tec).features) |
|
.enter() |
|
.append('path') |
|
.attr('class', 'geo tec'); |
|
|
|
// graticules |
|
svg.append('path').attr('class', 'geo graticule') |
|
.datum(d3.geoGraticule10()); |
|
|
|
const voronoi = d3.geoVoronoi() |
|
.x(d => d.lon) |
|
.y(d => d.lat) |
|
(volcanoes); |
|
|
|
// voronoi polygons |
|
svg.append('g').selectAll('.voronoi') |
|
.data(voronoi.polygons().features) |
|
.enter().append('path') |
|
.attr('class', 'geo voronoi') |
|
.append('title').text(({properties: { site: d}}) => `${d.name}, ${d.country} (${d.type}) [${d.elevation}m]`); |
|
|
|
// urquhart links |
|
var u = voronoi.links(); |
|
u.features = u.features.filter(d => d.properties.urquhart) |
|
svg.selectAll('.urquhart') |
|
.data(u.features) |
|
.enter() |
|
.append('path') |
|
.attr('class', 'geo urquhart'); |
|
|
|
|
|
// volcano points |
|
svg.append('path') |
|
.attr('class', 'geo volcanoes') |
|
.datum({ |
|
type: 'MultiPoint', |
|
coordinates: volcanoes.map(d => ([d.lon, d.lat])) |
|
}); |
|
|
|
render(); |
|
}); |
|
|
|
// |
|
|
|
function render() { |
|
svg.selectAll('path.geo').attr('d', path); |
|
svg.selectAll('.graticule') |
|
.style('display', controls['Graticule Grid'] ? null : 'none'); |
|
svg.selectAll('.volcanoes') |
|
.style('display', controls['Volcanoes'] ? null : 'none'); |
|
svg.selectAll('.voronoi') |
|
.style('display', controls['Voronoi Layer'] ? null : 'none'); |
|
svg.selectAll('.urquhart') |
|
.style('display', d => { |
|
//console.log(d); |
|
if (controls['Urquhart Layer'] && (d.properties.length < controls['Max dist.'])) return null; // visible |
|
else return 'none'; |
|
}) |
|
} |
|
|
|
|
|
var inertia = d3.geoInertiaDrag(svg, function() { render(); }); |
|
</script> |
|
</body> |