map = {
let width = 960;
let height = 500;
let svg = d3
.create('svg')
.attr('id', 'worldMap')
.attr('viewBox', "0 0 " + width + " " + height)
.attr('preserveAspectRatio', 'xMinYMin meet');
let projection = d3
.geoRobinson()
.center([0, 0])
.scale(120)
.rotate([0, 0]);
let path = d3.geoPath().projection(projection);
let g = svg.append("g");
g.append("path")
.datum({ type: "Sphere" })
.attr("class", "water")
.attr('fill', '#D0E1D4')
.attr("d", path);
g.selectAll(".countries")
.data(topojson.feature(world, world.objects.countries).features)
.enter()
.append("path")
.attr("d", path)
.attr("class", 'countries')
.attr('fill', '#F2F6D0')
.attr('stroke', '#D0E1D4');
g.selectAll(".cities")
.data(citiesRaw)
.enter()
.append("path")
.attr('class', 'cities')
.attr('fill', '#EDAFB8')
.attr('stroke', 'none')
.attr('stroke-width', 0)
.attr('d', function(e) {
return path(
d3
.geoCircle()
.center([e.Longitude, e.Latitude])
.radius(1.5)()
);
})
.attr('id', function(e) {
let idName = e.City.split(' ').join('_');
return idName;
})
.attr('cursor', 'pointer')
.on('click', async function(f) {
d3.selectAll('.cities')
.transition()
.duration(500)
.attr('fill', '#EDAFB8')
.attr('stroke', 'white')
.attr('stroke-width', 0);
d3.select(this)
.transition()
.duration(500)
.attr('fill', 'magenta');
let peers = await simpleQuery(f);
peers = peers[topic];
for (let i = 0; i < peers.length; i++) {
let peer = peers[i];
d3.select("#" + peer.City.split(' ').join('_'))
.raise()
.transition()
.duration(1000)
.attr('fill', '#71697A')
.attr('stroke', topicStyles[topic].color)
.attr('stroke-width', 3);
}
})
.on('mouseover', function(e) {
d3.select(this)
.raise()
.transition()
.attr('stroke', '#71697A')
.attr('stroke-width', 1);
})
.on('mouseout', function(e) {
d3.select(this)
.transition()
.attr('stroke', 'white')
.attr('stroke-width', 0);
});
const zoom = d3
.zoom()
.scaleExtent([1, 10])
.on("zoom", () => {
g.attr("transform", d3.event.transform);
});
svg.call(zoom);
return svg.node();
}