Built with blockbuilder.org
xxxxxxxxxx
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="//d3js.org/d3-geo-projection.v1.min.js"></script>
<script src="//d3js.org/topojson.v2.min.js"></script>
<style>
body { margin:0;position:fixed;top:0;right:0;bottom:0;left:0; }
.graticule {
fill: none;
stroke: #777;
stroke-width: .5px;
stroke-opacity: .5;
}
.sphere {
fill: #7BB5FF;
}
.gradient {
fill: url(#gradient);
}
.country {
fill: #404F24;
fill-opacity: 0.7;
stroke: #eee;
stroke-width: 0.2;
}
</style>
</head>
<body>
<script>
function createMap() {
var width = 800,
height = 800,
scale = 300,
lastX = 0,
origin = {
x: 55,
y: 0
};
var svg = d3.select('body').append('svg')
.style('width', 1000)
.style('height', 1000)
.style('border', '1px black solid')
var projection = d3.geoOrthographic()
.scale(scale)
.translate([width / 2, height / 2])
.rotate([origin.x, origin.y])
.center([0, 0])
.clipAngle(90);
var geoPath = d3.geoPath()
.projection(projection);
var graticule = d3.geoGraticule();
var sphere = {type: "Sphere"};
// setup the gradient to make the earth look brighter at top left
var gradient = svg.append("svg:defs")
.append("svg:linearGradient")
.attr("id", "gradient")
.attr("x1", "0%")
.attr("y1", "0%")
.attr("fx1", "50%")
.attr("fy1", "50%")
.attr("x2", "100%")
.attr("y2", "100%")
.attr("spreadMethod", "pad");
gradient.append("svg:stop") // middle step setting
.attr("offset", "50%")
.attr("stop-color", "#fff")
.attr("stop-opacity", 0.6);
gradient.append("svg:stop") // final step setting
.attr("offset", "100%")
.attr("stop-color", "#006")
.attr("stop-opacity", 0.6);
// end setup gradient
// zoom AND rotate
svg.call(d3.zoom().on('zoom', zoomed));
// code snippet from https://stackoverflow.com/questions/36614251
var λ = d3.scaleLinear()
.domain([-width, width])
.range([-180, 180])
var globe = svg.append('g');
// Draw the sphere for the earth
globe.append("path")
.datum(sphere)
.attr("class", "sphere")
.attr("d", geoPath);
// draw a gradient sphere because it looks cool
globe.append("path")
.datum(sphere)
.attr("class", "gradient")
.attr("d", geoPath)
globe.append('path')
.datum(graticule)
.attr('class', 'graticule')
.attr('d', geoPath);
d3.json('world-110m.json').then(function(world) {
var countries = topojson.feature(world, world.objects.countries).features;
// draw country outlines
globe.selectAll('.country')
.data(countries)
.enter()
.append('path')
.attr('class', 'country')
.attr('d', geoPath);
});
function zoomed() {
var transform = d3.event.transform;
var r = {
x: λ(transform.x),
};
// var k = Math.sqrt(100 / projection.scale());
// if (d3.event.sourceEvent.wheelDelta) {
// projection.scale(scale * transform.k)
// transform.x = lastX;
// } else {
projection.rotate([origin.x + r.x, 0]);
lastX = transform.x;
// }
updatePaths(globe, graticule, geoPath);
};
};
function updatePaths(globe, graticule, geoPath) {
globe.selectAll('path.graticule').attr('d', geoPath);
globe.selectAll('path.country').attr('d', geoPath);
};
createMap();
</script>
</body>
https://d3js.org/d3.v5.min.js
https://d3js.org/d3-geo-projection.v1.min.js
https://d3js.org/topojson.v2.min.js