I am trying to rotate a globe (orthographic projection). What I have now does rotate the globe, though it is very choppy, and it breaks how the map looks after i drag it (graticules and ocean fill)
How can I improve my code to make it better? Here is the relevant code:
const svg = d3.select('svg');
const projection = d3.geoOrthographic()
const graticule = d3.geoGraticule();
let pathGenerator = d3.geoPath().projection(projection);
const g = svg.append('g');
g.append('path')
.attr('class', 'sphere')
.attr('d', pathGenerator({type: 'Sphere'}));
g.append('path')
.datum(graticule)
.attr("class", "graticule")
.attr("d", pathGenerator);
g.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
g.call(d3.zoom().on('zoom', () => {
g.attr('transform', d3.event.transform)
}));
function dragstarted(){
console.log("started");
}
function dragged(){
const rotate = projection.rotate()
const k = 75 / projection.scale()
//console.log(k);
projection.rotate([
rotate[0] + d3.event.dx * k,
rotate[1] - d3.event.dy * k
])
pathGenerator = d3.geoPath().projection(projection)
svg.selectAll("path").attr("d", pathGenerator)
}
function dragended(){
console.log("drag ended");
}
edit: Live demo: https://vizhub.com/Glebenator/f44ac266b14f4c92b88113fcc89c389d?edit=files&file=index.html
Okay so I did two things.
Inside of the dragged
function instead of selecting all the path elements as one I selected them individually... so replace the line svg.selectAll("path").attr("d", pathGenerator)
with svg.selectAll(".graticule").attr("d", pathGenerator)
and svg.selectAll(".country").attr("d", pathGenerator)
.
When you append the countries you use selectAll('path') like this g.selectAll('path').data(countries.features)
... I think this confuses d3 because you have already appended some path elements so I changed it to a unique selector like this g.selectAll('.country').data(countries.features)
.
I'm not 100% sure why d3 behaves like that (maybe @AndrewReid can shed some light) but i've learned from experience that it's best practice to use unique selectors when appending and updating SVG elements with d3.