Created
November 10, 2022 23:07
-
-
Save jadiehm/3d14cdeeb34642020dd0f813c2b8a232 to your computer and use it in GitHub Desktop.
Rotating globe with markers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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