如何在平移时阻止Google地图上叠加层的水平包装?

时间:2013-07-18 18:26:20

标签: google-maps d3.js geojson overlays

我创建了一个页面,允许用户在Google地图上突出显示国家/地区。我的代码很简单 - 我正在使用D3.js和google的OverlayView - 我抓住了国家from here的地理json。

一切都很好 - 但是当一个国家跨越地图的最边缘时,我的国家大纲有时会错误地穿过地图的中心。例如,如果地图被淘汰,那么中国的西半部位于最右边,而东半部位于最左边。这是发生了什么。

enter image description here

注意:这似乎是地图平移问题,与缩放级别没有关系 - 这是地图的最小缩放设置为2的相同问题

enter image description here

有关如何在平移地图时避免此效果的任何想法?提前谢谢!

更新#1(2013.07.18)

非常感谢您的回答和评论。我创建了一个very simple example of my issue。此测试页面在谷歌地图上概述了中国,并以美国为中心(因此您可以在加载时看到问题)。注意在任一方向平移都可以解决问题,放大美国似乎无济于事。再次感谢!

2 个答案:

答案 0 :(得分:1)

这个问题演示了如何控制叠加缩放范围和平移范围,以防止包装,只是不允许用户一次看到整个世界。

Prevent horizontal world-wrapping of overlays in GMap v3

问题的关键在于OverlayView获取像素坐标的位置。如果我们能够弄清楚如何改进那部分以保持形状在一起,它可以解决我们的问题。这可能有助于测试包装,但它可能不起作用,因为即使我们放大你的问题似乎也会发生。

var proj = overlay.getProjection();
var wwidth = 0;
if (proj) wwidth = proj.getWorldWidth();
var mapsWrapsAround=false;
if (__wwidth > 0 && __wwidth < domContainer.width()) mapsWrapsAround = true;

我意识到测试经度是否与开始经度有所不同可能不起作用,因为经度可能是正确的,但是映射到屏幕上的多个div位置。所以这是我们必须测试的div像素坐标。但是也许你可以通过测试它是否在与地理坐标的差异相反的方向来测试x中的翻转。

// UNTESTED

// dimensioned somewhere outside
var start;
var startgeo;

// inside the overlay.onAdd content I think.
// Turn the overlay projection into a d3 projection
var googleMapProjection = function (coordinates) {
    var googleCoordinates = new google.maps.LatLng(coordinates[1], coordinates[0]);
    var pixelCoordinates = overlayProjection.fromLatLngToDivPixel(googleCoordinates);
    var proj = overlay.getProjection();
    var worldwidth = proj.getWorldWidth();
    var finalX = pixelCoordinates.x;

    if(typeof(start) === "undefined"){
        start = pixelCoordinates;
        startgeo = googleCoordinates;
    }
    else {
        if(pixelCoordinates.x > start.x && googleCoordinates.lng() < startgeo.lng()){
              finalX -= worldwidth;
        }
        else if(pixelCoordinates.x < start.x && googleCoordinates.lng() > startgeo.lng()){
             finalX += worldwidth;                     
        } 
    }
    return [finalX, pixelCoordinates.y];
}

所以这样做是假设谷歌地图为每个坐标选择了最接近北美的屏幕位置。如果形状正确地保持在一起,那么如果结束经度大于起始经度,那么结束像素.X也应该大于起始像素.X。但是,如果投影返回了世界另一侧的点,那么相对于起始像素的新像素应该在错误的方向上。也就是说,end.x现在小于start.x。因此,为了解决这个问题,我们只需按照解决问题的方向调整世界宽度。希望。

答案 1 :(得分:0)

非常感谢Ted指出我正确的方向 - 我试图将你的答案标记为正确但不幸的是我仍然在编辑你的答案时遇到问题。

无论如何,here is a simple sample实现了解决方案。我们提出的策略是跟踪我们处理的最后一点的经度。处理新点时,如果我们看到一个点突然发生了跳跃(在x方向上) - 我们假设它被包裹起来,我们加上或减去世界的宽度,将点移回其他点来自那个国家。

这是overlay.draw函数中修复的内容

var markerOverlay = this;
var overlayProjection = markerOverlay.getProjection();
var worldwidth = overlayProjection.getWorldWidth();
var prevX = null;

// Turn the overlay projection into a d3 projection
var googleMapProjection = function (coordinates) {
    var googleCoordinates = new google.maps.LatLng(coordinates[1], coordinates[0]);
    var pixelCoordinates = overlayProjection.fromLatLngToDivPixel(googleCoordinates);
    if (prevX != null) {
        // Check for a gigantic jump to prevent wrapping around the world
        var dist = pixelCoordinates.x - prevX;
        if (Math.abs(dist) > (worldwidth * 0.9)) {
            if (dist > 0) { pixelCoordinates.x -= worldwidth } else { pixelCoordinates.x += worldwidth }
        }
    }
    prevX = pixelCoordinates.x;
    return [pixelCoordinates.x + 10000, pixelCoordinates.y + 10000];
}