globe = {
const width = 500, height = 500;
const mapRadius = height / 3;
const projection = d3.geoOrthographic()
.scale(mapRadius)
.precision(0.1)
.translate([width / 2, height / 2]);
const path = d3.geoPath().projection(projection);
const color = d3.scaleOrdinal(d3.schemeAccent)
.domain(airlines);
const createGlobe = () => {
const countriesGroup = d3.create('svg:g');
countriesGroup
.append('circle')
.attr('id', 'atmoshpere')
.attr('filter', 'url(#atmosphere-glow)')
.attr('cx', width / 2)
.attr('cy', height / 2)
.attr('r', mapRadius);
countriesGroup
.append('circle')
.attr('id', 'ocean')
.attr('cx', width / 2)
.attr('cy', height / 2)
.attr('r', mapRadius);
countriesGroup
.selectAll('path')
.data(topojson.features)
.enter()
.append('path')
.attr('d', path)
.attr('id', d => `country ${d.properties.iso_a3}`)
.attr('filter', d => countriesVisisted.has(d.properties.name) ? 'url(#path-glow)' : undefined)
.attr('class', d => countriesVisisted.has(d.properties.name) ? 'country highlight' : 'country');
countriesGroup
.selectAll('.flightarc')
.data(flightArcs)
.enter()
.append('path')
.attr('class', 'flightarc')
.attr('filter', 'url(#path-glow)')
.style('stroke', d => color(d.airline))
.attr('d', path);
return countriesGroup;
};
const setupRotationAndAtmosphere = () => {
const atmosphereFlicker = (flickerAmount = 1) => {
const newAtmosphereRadius = 10 + Math.random() * flickerAmount;
const atmosphereSVGElement = document.getElementById('atmosphere-offset');
if (atmosphereSVGElement) {
atmosphereSVGElement.setAttribute('dx', newAtmosphereRadius);
atmosphereSVGElement.setAttribute('dy', newAtmosphereRadius);
}
};
let prevTime = 0;
const latestRotation = [0, 0];
d3.timer(time => {
const rotationX = latestRotation[0] - (((prevTime - time) * 360) / 30000);
latestRotation[0] = rotationX <= -180 ? 180 : rotationX;
latestRotation[1] = Math.sin(time / 2000) * (width / 100);
projection.rotate(latestRotation);
d3.selectAll('path').attr('d', path);
prevTime = time;
atmosphereFlicker();
});
};
const myGlobe = createGlobe();
setupRotationAndAtmosphere();
return myGlobe;
}