1

I am working on project to depict different data on world ocean map. You can find development version on github pages. To depict data on map select "variable", then (better) select "type" "Statistical mean" and click "show" button on top bar.

To render map initially i calculate projection using this code:

var scale = this.width / 640 * 100;
var offset = [this.width / 2, this.height / 2];
this.projection = d3.geo.equirectangular()
  .rotate([-180, 0])
  .scale(scale)
  .translate(offset)
var path = d3.geo.path().projection(this.projection);

And then recalculate map projection using code taked from here:

d3.json("data/map/world-50m.json", function(error, world) {
  ...
  var bounds  = path.bounds(topojson.feature(world, world.objects.land));
  var hscale  = scale * self.width  / (bounds[1][0] - bounds[0][0]);
  var vscale  = scale * self.height / (bounds[1][1] - bounds[0][1]);
  scale   = (hscale < vscale) ? hscale : vscale;
  offset  = [self.width - (bounds[0][0] + bounds[1][0])/2, self.height - (bounds[0][1] + bounds[1][1])/2];
  /*
   * Update projection.
   */
  self.projection
    .scale(scale)
    .translate(offset);
  path = d3.geo.path().projection(self.projection);
  ...
}

It works fine and finally i get full screen/width map. But then user can select part of map using dragging and zoom into selected area. So when small area of map is selected it works not very bed (but not perfect): enter image description here But when zoom into big area everything breakdown: enter image description here

Both screenshots shows how to select area. Click on "zoom" icon at the top left corner of selection to see result.

Code which i use to calculate new projection looks like:

/*
 * Coordinates of selection (rectangle area).
 */
var leftX      = state.leftX;
var topY       = state.topY;
var rightX     = state.rightX;
var bottomY    = state.bottomY;
/*
 * Calculate new map center.
 */
var areaWidth  = rightX - leftX;
var areaHeight = bottomY - topY;
var projectionCenter = state.inProjection.invert(
  [leftX + (areaWidth / 2), bottomY - (areaHeight / 2)]
);
/*
 * Calculate new scale factor.
 */
var widthAspectRatio  = areaWidth  / this.map.width;
var heightAspectRatio = areaHeight / this.map.height;

var widthScale  = state.inProjection.scale() / widthAspectRatio;
var heightScale = state.inProjection.scale() / heightAspectRatio;

var projectionScale;
if (widthScale < heightScale) {
  projectionScale = widthScale;
} else {
  projectionScale = heightScale;
}
/*
 * Update projection.
 */
state.outProjection = d3.geo.equirectangular()
  .rotate([0, 0, 0])
  .scale(projectionScale)
  .center(projectionCenter);

I can't understand why it works incorrect? I think problem with rotation or may be with centering... or may be with translate. Can anyone explain me how to zoom into correct?

Community
  • 1
  • 1
zeleniy
  • 2,232
  • 19
  • 26
  • See https://stackoverflow.com/questions/14492284/center-a-map-in-d3-given-a-geojson-object -- the only difference in your case is that you're getting the coordinates of the bounding box from the zoom and not the object. – Lars Kotthoff Oct 16 '15 at 21:44

0 Answers0