【问题标题】:Pan to "usable part" of Google Map平移到谷歌地图的“可用部分”
【发布时间】:2014-06-11 15:44:11
【问题描述】:

我正在使用 Google Maps API 在网页中嵌入地图。地图填满了整个屏幕,但屏幕左侧有大约 400 像素的内容,大部分覆盖了地图。当我想平移地图时,左侧的区域应该被视为不可见。

我想出了以下代码来计算地图的“可用部分”,我希望距离地图边缘 50 像素,并且还应该避开地图左侧的 400 像素区域:

panIfNotClose = function(latLngs){
    if(latLngs.length === 0)
        return;

    // Get some important values that may not be available yet
    // http://stackoverflow.com/a/2833015/802335
    var bounds = map.getBounds();
    if(!bounds)
        return setTimeout(panIfNotClose.bind(this, latLngs), 10);
    var overlay = new google.maps.OverlayView();
    overlay.draw = function(){};
    overlay.setMap(map);
    var proj = overlay.getProjection();
    if(!proj)
        return setTimeout(panIfNotClose.bind(this, latLngs), 10);

    // Calculate the "usable part" of the map
    var center = bounds.getCenter();
    var northEast = bounds.getNorthEast();
    var southWest = bounds.getSouthWest();
    var northEastPx = proj.fromLatLngToContainerPixel(northEast);
    var southWestPx = proj.fromLatLngToContainerPixel(southWest);
    var menuPadding = 400;
    var newNorthEastPx = new google.maps.Point(northEastPx.x + 50, northEastPx.y + 50);
    var newSouthWestPx = new google.maps.Point(southWestPx.x - (50 + menuPadding), southWestPx.y - 50);
    var newNorthEast = proj.fromContainerPixelToLatLng(newNorthEastPx);
    var newSouthWest = proj.fromContainerPixelToLatLng(newSouthWestPx);
    var centerBounds = new google.maps.LatLngBounds(newSouthWest, newSouthWest);

    // Decide if any of the new LatLngs are far enough away that the map should move 
    var shouldMove = false;
    var targetBounds = new google.maps.LatLngBounds();
    for(var i = 0; i < latLngs.length; i++){
        targetBounds.extend(latLngs[i]);
        if(!centerBounds.contains(latLngs[i]))
            shouldMove = true;
    }

    // If the LatLngs aren't all near the center of the map, pan to it
    if(latLngs.length === 1){
        if(shouldMove || map.getZoom() !== 18)
            map.panTo(latLngs[0]);
        map.setZoom(18);
    }else{
        var targetZoom = Math.min(getBoundsZoomLevel(targetBounds), 18);
        if(shouldMove || map.getZoom() !== targetZoom)
            map.panTo(targetBounds.getCenter());
        map.setZoom(targetZoom);
    }
}

此代码应测试“有效”区域以确保所有给定的 LatLngs 都适合其中,但它尚未对 panTo 进行任何更改以将中心“移动”到帐户右侧 200 像素对于左侧 400px 的内容。

代码没有按我的预期工作,但我不知道为什么。我怀疑从LatLng 转换为Point 时我可能做错了什么,反之亦然。我也可能做的工作比必要的多得多,尽管我想不出一种方法来简化它。

【问题讨论】:

  • V3中没有函数getBoundsZoomLevel
  • 我实际上从我的代码中其他地方定义的链接答案中获得了确切的功能(注意它没有以map. 为前缀)。我没有包括它,因为它与我的问题并不真正相关。

标签: javascript google-maps-api-3


【解决方案1】:

结果证明这是一个非常简单的错误。在var centerBounds = new google.maps.LatLngBounds(newSouthWest, newSouthWest); 行中,我不小心使用了两次相同的 LatLng,而不是东北角和西南角。在计算newNorthEastPxnewSouthWestPx 时,我也遇到了一些简单的算术问题。使用centerBounds 绘制google.maps.Rectangle 有助于快速轻松地解决这个问题。对于任何感兴趣的人,这是最终结果:

function panIfNotClose(latLngs, zoomOnly){
    if(latLngs.length === 0)
        return;

    if(typeof latLngs !== "object")
        latLngs = [latLngs];

    // Calculate the "middle half" of the map
    var bounds = map.getBounds();
    if(!bounds) // http://stackoverflow.com/a/2833015/802335
        return setTimeout(panIfNotClose.bind(this, latLngs, zoomOnly), 10);
    var overlay = new google.maps.OverlayView();
    overlay.draw = function(){};
    overlay.setMap(map);
    var proj = overlay.getProjection();
    if(!proj)
        return setTimeout(panIfNotClose.bind(this, latLngs, zoomOnly), 10);

    var center = bounds.getCenter();
    var northEast = bounds.getNorthEast();
    var southWest = bounds.getSouthWest();
    var northEastPx = proj.fromLatLngToContainerPixel(northEast);
    var southWestPx = proj.fromLatLngToContainerPixel(southWest);
    var menuPadding = 0;
    if($navBar.css("display") !== "none")
        menuPadding = 400;
    var newNorthEastPx = new google.maps.Point(northEastPx.x - 100, northEastPx.y + 100);
    var newSouthWestPx = new google.maps.Point(southWestPx.x + (100 + menuPadding), southWestPx.y - 100);
    var newNorthEast = proj.fromContainerPixelToLatLng(newNorthEastPx);
    var newSouthWest = proj.fromContainerPixelToLatLng(newSouthWestPx);
    centerBounds = new google.maps.LatLngBounds(newSouthWest, newNorthEast);

    var shouldMove = false;
    var targetBounds = new google.maps.LatLngBounds();
    for(var i = 0; i < latLngs.length; i++){
        targetBounds.extend(latLngs[i]);
        if(!centerBounds.contains(latLngs[i]))
            shouldMove = true;
    }

    // If the marker isn't near the center of the map, pan to it
    if(latLngs.length === 1){
        if(!zoomOnly && (shouldMove || map.getZoom() !== 18))
            map.panTo(correctCenter(latLngs[0], proj));
        map.setZoom(18);
    }else{
        var targetZoom = Math.min(getBoundsZoomLevel(targetBounds), 18);
        if(!zoomOnly && (shouldMove || map.getZoom() !== targetZoom))
            map.panTo(correctCenter(targetBounds.getCenter(), proj));
        map.setZoom(targetZoom);
    }
}

function correctCenter(latLng, proj){
    // $navBar references a jQuery pointer to a DOM element
    if($navBar.css("display") === "none")
        return latLng;
    var latLngPx = proj.fromLatLngToContainerPixel(latLng);
    var newLatLngPx = new google.maps.Point(latLngPx.x - 200, latLngPx.y)
    return proj.fromContainerPixelToLatLng(newLatLngPx);
}

// Adapted from http://stackoverflow.com/a/13274361/802335
function getBoundsZoomLevel(bounds){
    // $mapCanvas is a jQuery reference to the div containing the Google Map
    var mapDim = {
        width: $mapCanvas.width() * .6,
        height: $mapCanvas.height() * .6
    };
    var ZOOM_MAX = 18;

    function latRad(lat){
        var sin = Math.sin(lat * Math.PI / 180);
        var radX2 = Math.log((1 + sin) / (1 - sin)) / 2;
        return Math.max(Math.min(radX2, Math.PI), -Math.PI) / 2;
    }

    function zoom(mapPx, fraction){
        return Math.floor(Math.log(mapPx / 256 / fraction) / Math.LN2);
    }

    var ne = bounds.getNorthEast();
    var sw = bounds.getSouthWest();

    var latFraction = (latRad(ne.lat()) - latRad(sw.lat())) / Math.PI;

    var lngDiff = ne.lng() - sw.lng();
    var lngFraction = ((lngDiff < 0) ? (lngDiff + 360) : lngDiff) / 360;

    var latZoom = zoom(mapDim.height, latFraction);
    var lngZoom = zoom(mapDim.width, lngFraction);

    return Math.min(latZoom, lngZoom, ZOOM_MAX);
}

【讨论】:

    猜你喜欢
    • 2012-04-10
    • 2011-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-28
    • 1970-01-01
    • 1970-01-01
    • 2012-01-06
    相关资源
    最近更新 更多