d3.js.如何放大地图的选定区域?

时间:2015-10-16 20:35:45

标签: dictionary d3.js projection zooming

我正在研究描绘世界海洋地图上不同数据的项目。您可以在github pages上找到开发版本。要在地图上描绘数据,请选择“变量”,然后(更好)选择“类型”“统计平均值”并点击顶部栏上的“显示”按钮。

要初始渲染地图,我使用以下代码计算projection

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);

然后使用从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);
  ...
}

它工作正常,最后我得到全屏/宽度图。但是,用户可以使用拖动和缩放选择区域来选择地图的一部分。因此,当选择小面积的地图时,它的工作效果不是很好(但并不完美): enter image description here 但是当放大到大区域时一切都会崩溃: enter image description here

两个屏幕截图都显示了如何选择区域。单击选择左上角的“缩放”图标以查看结果。

我用来计算新投影的代码如下:

/*
 * 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);

我无法理解为什么它的工作原理不正确?我认为旋转问题或可能与居中...或可能与翻译。任何人都可以解释我如何放大到正确吗?

0 个答案:

没有答案