Skip to content

Instantly share code, notes, and snippets.

@jadiehm
Created November 10, 2022 23:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jadiehm/3d14cdeeb34642020dd0f813c2b8a232 to your computer and use it in GitHub Desktop.
Save jadiehm/3d14cdeeb34642020dd0f813c2b8a232 to your computer and use it in GitHub Desktop.
Rotating globe with markers
<html>
<head>
<script src="https://d3js.org/d3.v7.min.js"></script>
<script src="https://unpkg.com/topojson@3.0.2/dist/topojson.js"></script>
</head>
<script>
// globe configurations
const width = 1000;
const height = 500;
const config = {
speed: 0.025,
verticalTilt: -10,
horizontalTilt: 0
}
const projection = d3.geoOrthographic();
const intitalScale = projection.scale();
const path = d3.geoPath().projection(projection);
const center = [width/2, height/2];
// dom elements
let svg;
let markerGroup;
// data
const files = ["https://gist.githubusercontent.com/mbostock/4090846/raw/d534aba169207548a8a3d670c9c2cc719ff05c47/world-110m.json"];
let worldData;
const locations = [
{"latitude": 43.6591, "longitude": -70.2568},
{"latitude": 41.2033, "longitude": -77.1945},
{"latitude": 40.7128, "longitude": -74.0060},
{"latitude": 37.0902, "longitude": -95.7129},
{"latitude": 38.9779, "longitude": -77.0075},
{"latitude": 40.6782, "longitude": -73.9442},
{"latitude": 33.7490, "longitude": -84.3880},
{"latitude": -40.9006, "longitude": 174.8860, "name": "georgia"},
{"latitude": 40.7128, "longitude": -74.0060},
{"latitude": 42.2775, "longitude": -71.3468},
{"latitude": 44.3148, "longitude": -85.6024},
{"latitude": 37.5407, "longitude": -77.436},
{"latitude": 38.9072, "longitude": -77.0369},
{"latitude": 37.7749, "longitude": -122.4194},
{"latitude": 44.3148, "longitude": -85.6024},
{"latitude": 36.7783, "longitude": -119.4179},
{"latitude": 52.3676, "longitude": 4.9041, "name": "gomer", "yOffset": 15},
{"latitude": 43.8041, "longitude": -120.5542, "name": "liz", "xOffset": -20},
{"latitude": 35.1495, "longitude": -90.0490, "name": "jay", "xOffset": -25, "yOffset": 20},
{"latitude": 43.6591, "longitude": -70.2568},
{"latitude": 40.6782, "longitude": -73.9442},
{"latitude": 41.878, "longitude": -93.0977},
{"latitude": 55.3781, "longitude": -3.4360, "name": "jade", "yOffset": -5},
{"latitude": 37.4419, "longitude": -122.143, "name": "anna", "xOffset": -40},
{"latitude": 43.3314, "longitude": -83.0458},
{"latitude": 39.0997, "longitude": -94.5786},
{"latitude": 32.254, "longitude": -110.9742, "name": "poozle", "xOffset": -45, "yOffset": 20},
{"latitude": 33.749, "longitude": -84.388},
{"latitude": 44.4759, "longitude": -73.2121},
{"latitude": 43.6532, "longitude": -79.3832},
{"latitude": 39.5501, "longitude": -105.7821, "name": "sergio", "xOffset": -20, "yOffset": -5},
{"latitude": 27.6648, "longitude": -81.5158, "name": "nicholas", "yOffset": 15},
{"latitude": 36.7783, "longitude": -119.4179},
{"latitude": 36.7783, "longitude": -119.4179},
{"latitude": 39.7684, "longitude": -86.1581},
{"latitude": 52.0705, "longitude": 4.3007, "name": "stijn", "xOffset": -35, "yOffset": 15},
{"latitude": 32.0809, "longitude": -81.0912},
{"latitude": 10.8505, "longitude": 76.2711, "name": "kripaaa"},
{"latitude": 28.3949, "longitude": 84.124, "name": "shaswot"},
{"latitude": 40.7128, "longitude": -74.006},
{"latitude": 46.7296, "longitude": -94.6859, "name": "cathy c"},
{"latitude": 40.4173, "longitude": -82.9071},
{"latitude": 56.1304, "longitude": -106.3468, "name": "brenna"},
{"latitude": 38.9072, "longitude": -77.0369},
{"latitude": 33.9519, "longitude": -83.3576},
{"latitude": 41.8781, "longitude": -87.6498},
{"latitude": 40.7128, "longitude": -74.0060, "name": "eli", "xOffset": 25}
];
function drawGlobe() {
console.log(svg)
svg.selectAll(".segment")
.data(topojson.feature(worldData, worldData.objects.countries).features)
.enter().append("path")
.attr("class", "segment")
.attr("d", path)
.style("stroke", "#aaa7a0")
.style("stroke-width", "1px")
.style("fill", (d, i) => '#dbd6ce')
.style("opacity", ".6");
}
function drawMarkers() {
const markers = markerGroup.selectAll('rect').data(locations);
markers
.enter()
.append('rect')
.merge(markers)
.attr('x', d => projection([d.longitude, d.latitude])[0])
.attr('y', d => projection([d.longitude, d.latitude])[1])
.attr('fill', d => {
const coordinate = [d.longitude, d.latitude];
let gdistance = d3.geoDistance(coordinate, projection.invert(center));
return gdistance > 1.57 ? 'none' : '#76a5d1';
})
.attr('stroke', d => {
const coordinate = [d.longitude, d.latitude];
let gdistance = d3.geoDistance(coordinate, projection.invert(center));
return gdistance > 1.57 ? 'none' : '#47637d';
})
.attr("stroke-width", "2px")
.attr('width', 8)
.attr('height', 8);
const labels = markerGroup.selectAll('text').data(locations);
labels
.enter()
.append("text")
.merge(labels)
.attr('fill', d => {
const coordinate = [d.longitude, d.latitude];
let gdistance = d3.geoDistance(coordinate, projection.invert(center));
return gdistance > 1.57 ? 'none' : '#18212a';
})
.attr("font-family", "sans-serif")
.attr("font-size", "16px")
.attr("font-weight", 700)
.attr('x', d => {
let xOffset = d.xOffset != undefined ? d.xOffset : 10;
return projection([d.longitude, d.latitude])[0] + xOffset
})
.attr('y', d => {
let yOffset = d.yOffset != undefined ? d.yOffset : 0;
return projection([d.longitude, d.latitude])[1] + yOffset
})
.merge(labels)
.text(d => {
if (d.name != undefined) {
return d.name
}
})
markerGroup.each(function () { this.parentNode.appendChild(this); });
}
function enableRotation() {
d3.timer(function (elapsed) {
projection.rotate([config.speed * elapsed + 40, config.verticalTilt, config.horizontalTilt]);
svg.selectAll("path").attr("d", path);
drawMarkers();
});
}
function init() {
Promise.all(files.map(url => d3.json(url))).then(function(values) {
worldData = values[0];
// dom elements
svg = d3.select("#graphic").append("svg")
.attr("width", width)
.attr("height", height)
markerGroup = svg.append("g")
drawGlobe();
enableRotation();
})
}
init();
</script>
<body>
<div id="graphic"></div>
<div class="bg"></div>
</body>
<style>
body {
background-color: #f3eee5;5
}
div {
position: absolute;
top: 50px;
}
#graphic {
z-index: 100;
}
.bg {
background-color: #f3eee5;
border-radius: 50%;
height: 500px;
width: 500px;
left: 238px;
z-index: 1;
box-shadow: 0px 0px 20px #aaa7a0;
}
</style>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment