叠加地图图块,仅显示矩形边界内的地图图块

Overlay map tiles, only display those within rectangle bounds

本文关键字:地图 边界 叠加 显示      更新时间:2023-09-26

我正在使用Google Maps API 3在几个美国绘制网格。在将我自己的解决方案(涉及迭代绘制超过 62,000 条折线)组合在一起后,我发现简单地将 Google 的叠加地图类型示例调整为我需要的网格大小要容易得多,强度也更低,其中缩放级别 20 时每个正方形的边长相当于 90 英尺。到目前为止,这运作良好。

我现在的问题是双重的:

  1. 我只需要绘制落在固定矩形多边形边界内的正方形。应该绘制整个卫星地图,但我只需要此区域内的网格叠加。划定部分重叠。
  2. 我还需要出现在每个网格方块左上角的数字,以便从此矩形的左上角开始计数。这意味着在缩放级别 20 时,每个坐标的长度不应超过 5 位,因为最大 X 值为 ~45300,最大 Y 值为 ~16800。目前,正方形从 90° N 180° W 开始计数,并在缩放级别 20 处具有六位数坐标。

我怀疑该解决方案涉及使用 poly.containsLocation() 检查每个网格方块的坐标(并且可能在zoom_changed上运行它),但 Google 的示例页面没有充分解释如何访问各个网格方块,所以我没有任何方法检查它们。

如何访问这些网格方块?还是我需要创建一个新的叠加视图?

到目前为止,我的代码如下。

var map;
function CoordMapType(tileSize) {
    this.tileSize = tileSize;
}
CoordMapType.prototype.getTile = function(coord, zoom, ownerDocument) {
    var div = ownerDocument.createElement('div');
    div.innerHTML = coord;
    div.style.width = this.tileSize.width + 'px';
    div.style.height = this.tileSize.height + 'px';
    div.style.fontSize = '10';
    div.style.color = '#FFFFFF';
    div.style.borderStyle = 'solid';
    div.style.borderWidth = '1px';
    div.style.borderColor = '#FFFFFF';
    return div;
};
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
    center: {lat: 38.2711991, lng: -82.6292357},
    zoom: 7,
    mapTypeId: google.maps.MapTypeId.SATELLITE
});
map.overlayMapTypes.insertAt(0, new CoordMapType(new google.maps.Size(233, 233)));
gridBox();
}
function gridBox(){
    var gridBox = [
        new google.maps.LatLng(40.638, -75.387),
        new google.maps.LatLng(36.497, -75.387),
        new google.maps.LatLng(36.497, -89.539),
        new google.maps.LatLng(40.638, -89.539),
    ];
    gridBoxSet = new google.maps.Polygon({
        path: gridBox,
        geodesic: false,
        strokeColor: "#AAAAAA",
        strokeOpacity: 1,
        strokeWeight: 4,
        fillColor: "#FFFFFF",
        fillOpacity: 0.2
    });
    gridBoxSet.setMap(map);
}

Google Maps JavaScript API 提供了一个 OverlayView 类,用于创建您自己的自定义叠加层。OverlayView 是一个基类,它提供了创建叠加时必须实现的几种方法。该类还提供了一些方法,可以在屏幕坐标和地图上的位置之间进行转换。

添加自定义叠加

以下是创建自定义叠加所需步骤的摘要:

  • 将自定义覆盖对象的原型设置为 google.maps.OverlayView() 的新实例。实际上,这将对覆盖类进行子类化。
  • 为自定义覆盖创建构造函数,并设置任何初始化参数。
  • 在原型中实现onAdd()方法,并将叠加附加到地图。 当地图准备好附加叠加时,将调用OverlayView.onAdd()
  • 在原型中实现 draw() 方法,并处理对象的可视显示。 首次显示对象时将调用OverlayView.draw()
  • 您还应该实现一个onRemove()方法来清理您在覆盖中添加的任何元素。

您还可以在此处查看完整的工作示例:https://developers.google.com/maps/documentation/javascript/examples/overlay-simple

在意识到getTile方法如何将坐标值写入每个div的innerHTML之后,我想出了如何限制绘制哪些坐标值。这是我的代码。它非常笨拙,不会直接检查瓷砖的边界,但它有效并且性能方面非常流畅。

var map;
var zoom;
function CoordMapType() {
    this.tileSize = new google.maps.Size(233, 233);
}
var firstX = 289496; //coord.x of top left of rectangle
var firstY = 433476; //coord.y of top left of rectangle
var lastX = 45290; //width of rectangle in tiles
var lastY = 16959; //height of rectangle in tiles
CoordMapType.prototype.getTile = function(coord, zoom, ownerDocument) {
    var coordX = coord.x-(firstX/(Math.pow(2,(20-zoom))));
    var coordY = coord.y-(firstY/(Math.pow(2,(20-zoom))));
    var maxX = lastX/(Math.pow(2,(20-zoom)));
    var maxY = lastY/(Math.pow(2,(20-zoom)));
    var div = ownerDocument.createElement('div');
    div.innerHTML = "("+coordX.toFixed(0)+","+coordY.toFixed(0)+")";
    div.style.width = this.tileSize.width + 'px';
    div.style.height = this.tileSize.height + 'px';
    div.style.fontSize = '10';
    div.style.color = '#FFFFFF';
    div.style.borderStyle = 'solid';
    div.style.borderWidth = '1px';
    div.style.borderColor = '#FFFFFF';
    if((coordX>-1 && coordX<maxX) && (coordY>-1 && coordY<maxY)){
        return div;
    } else{
        return null;
    }
};
function initMap() {
    map = new google.maps.Map(document.getElementById('map'), {
        center: {lat: 38.2711991, lng: -82.6292357},
        zoom: 7,
        mapTypeId: google.maps.MapTypeId.SATELLITE
    });
    map.setTilt(0);
    map.addListener('zoom_changed', function() {
        zoom = map.getZoom();
        console.log(zoom);
    });
    drawGrid();
    map.overlayMapTypes.insertAt(0, new CoordMapType());
}