12

Apologies if this is a simple case of me being blind to the obvious, but I am trying to put together a page that shows a map of the world (data sourced from a TopoJSON file) in Mercator projection centered on the Pacific. I.e. Europe on the left, America on the right and Australia in the middle. A bit like this...

The Pacific Centered World

From this point I want to be able to zoom and pan the map to my hearts desire, but when I pan east or west, I want the map to scroll 'around' and not come to the end of the World (I hope that makes sense).

The code I am currently working on is here (or at the following Gist (https://gist.github.com/d3noob/4966228) or block (http://bl.ocks.org/d3noob/4966228));

<!DOCTYPE html>
<meta charset="utf-8">
<style>
body {font-size:11px;}
path {
  stroke: black;
  stroke-width: 0.25px;
}
</style>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/topojson.v0.min.js"></script>
<script>
var width = 960,
    velocity = .005,  
    then = Date.now() 
    height = 475;

var projection = d3.geo.mercator()
    .center([0, 0 ])
    .scale(1000);

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

var path = d3.geo.path()
    .projection(projection);

var g = svg.append("g");


d3.json("world-110m.json", function(error, topology) {
  g.selectAll("path")
    .data(topojson.object(topology, topology.objects.countries).geometries)
  .enter()
    .append("path")
    .attr("d", path)
    .style("fill","black")
    
  d3.timer(function() {  
    var angle = velocity * (Date.now() - then);  
    projection.rotate([angle,0,0]);  
    svg.selectAll("path")  
      .attr("d", path.projection(projection));  
  }); 
  
  var zoom = d3.behavior.zoom()
  .on("zoom",function() {
    g.attr("transform","translate("+d3.event.translate.join(",")+")scale("+d3.event.scale+")")
  });
    
  svg.call(zoom)

});
</script>
</body>
</html>

The code is an amalgam of examples and as a result I can see a map that can rotate west to east automatically, and I can pan and zoom using the mouse, but when panning and zooming, from what I can tell, I am affecting the internal "g" element and not the map within the "svg" element.

There are plenty of good examples of being able to pan and zoom a map centered on the meridian. But none on the anti-meridian that I have discovered.

Any help would be greatly appreciated.

3 Answers 3

12

I ended up working on the same problem. Here's an example (see code) where you pan left/right to rotate the projection (with wraparound), and up/down to translate (clamped by max absolute latitude), with zoom as well. Ensures that projection always fits within viewbox.

I learned a lot about zoom behavior, and projection center() and rotate() interaction.

2
  • Awesome! That looks great. Good job and many thanks. I can see you've got some (to me) complex code in there. I will have to take some time to study it, but, that looks like exactly what I was trying to achieve. Cheers.
    – d3noob
    Commented Sep 20, 2013 at 17:57
  • The basic trick is just to separate mouse translation into up/down map translation and left/right map rotation. It's actually a bit similar to the [3D trackball rotation of the globe] (gist.github.com/patricksurry/5721459) I played with a while ago. Commented Sep 20, 2013 at 22:29
0

hope this code can solve your problem

    var projection = d3.geo.equirectangular()
    .center([0, 5])
    .scale(90)
    .translate([width / 2, height / 2])
    .rotate([0, 0])
    .precision(9);
1
  • Sorry, same problem exists with this projection. The answer provided by patriksurry above does a good job though. Cheers
    – d3noob
    Commented Nov 29, 2013 at 18:18
-2

Google maps on apple products work like this. Scrol left, and you will leave one Australia, then find another and another and another

Not the answer you're looking for? Browse other questions tagged or ask your own question.