我使用Google Maps API在网页中嵌入地图。地图填满了整个屏幕,但屏幕左侧有大约400px的内容,主要覆盖地图。当我想要平移地图时,应该将左边的区域视为不可见。
我想出了以下代码来计算"可用部分"我希望从地图的边缘开始50px的地图,并且还应该避免地图左侧的400px区域:
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);
}
}
此代码应测试&#34;有效&#34;区域以确保所有给定的LatLng
适合内部,但它尚未对panTo
进行任何更改以及#34;移动&#34;右边的中心200px占左边400px的内容。
代码并没有像我预期的那样工作,但我不确定原因。我怀疑从LatLng
转换为Point
或反之亦然时,我可能做错了。尽管我无法想出一种简化它的方法,但我也可能做了比必要更多的工作。
答案 0 :(得分:0)
这是一个非常简单的错误。在var centerBounds = new google.maps.LatLngBounds(newSouthWest, newSouthWest);
行中,我意外地使用了相同的LatLng两次,而不是东北角和西南角。在计算newNorthEastPx
和newSouthWestPx
时,我也遇到了一些简单的算术问题。使用google.maps.Rectangle
绘制centerBounds
有助于快速轻松地完成工作。对于任何感兴趣的人,最终结果如下:
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);
}