我正在研究描绘世界海洋地图上不同数据的项目。您可以在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);
...
}
它工作正常,最后我得到全屏/宽度图。但是,用户可以使用拖动和缩放选择区域来选择地图的一部分。因此,当选择小面积的地图时,它的工作效果不是很好(但并不完美): 但是当放大到大区域时一切都会崩溃:
两个屏幕截图都显示了如何选择区域。单击选择左上角的“缩放”图标以查看结果。
我用来计算新投影的代码如下:
/*
* 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);
我无法理解为什么它的工作原理不正确?我认为旋转问题或可能与居中...或可能与翻译。任何人都可以解释我如何放大到正确吗?