如何抵消谷歌地图API中心点

我有一张半透明面板覆盖了该地区的一部分的谷歌地图。 我想调整地图的中心点,以考虑部分遮挡的地图部分。 看到下面的图片。 理想情况下,十字准线和销子的位置将是地图的中心点。

我希望这是有道理的。

原因很简单:放大时,需要将地图放在十字准线上,而不是50%50%。 另外,我会在地图上绘制标记,并依次移动它们。 当地图以他们为中心时,他们也需要在偏移位置。

提前致谢!

我正在建造的地图的样机

一旦你find相关的以前的答案,这不是特别困难。

您需要将地图中心转换为世界坐标,find地图需要居中的位置,以便将视图中心放置在您想要的位置,然后使用真实中心重新alignment地图。

API将始终将地图居中放置在视口的中心,因此如果使用map.getCenter() ,则需要小心,因为它将返回实际中心,而不是表观中心。 我想这将有可能超载的API,以便它的getCenter()setCenter()方法被取代,但我没有这样做。

下面的代码。 在线示例 在这个例子中,点击button将地图的中心(有一个路口)向下移动100px,然后离开200px。

 function offsetCenter(latlng, offsetx, offsety) { // latlng is the apparent centre-point // offsetx is the distance you want that point to move to the right, in pixels // offsety is the distance you want that point to move upwards, in pixels // offset can be negative // offsetx and offsety are both optional var scale = Math.pow(2, map.getZoom()); var worldCoordinateCenter = map.getProjection().fromLatLngToPoint(latlng); var pixelOffset = new google.maps.Point((offsetx/scale) || 0,(offsety/scale) ||0); var worldCoordinateNewCenter = new google.maps.Point( worldCoordinateCenter.x - pixelOffset.x, worldCoordinateCenter.y + pixelOffset.y ); var newCenter = map.getProjection().fromPointToLatLng(worldCoordinateNewCenter); map.setCenter(newCenter); } 

还要看看地图对象上的panBy(x:number,y:number)函数。

文档中提到了这个function:

以给定的距离(以像素为单位)更改地图的中心。 如果距离小于地图的宽度和高度,则过渡将平滑animation。 请注意,地图坐标系统从西向东(对于x值)和从北到南(对于y值)增加。

就像这样使用它:

 mapsObject.panBy(200, 100) 

这是一个更简单的方法,可能在响应式devise中更有用,因为您可以使用百分比而不是像素。 没有世界坐标,没有LatLngs点!

 var center; // a latLng var offsetX = 0.25; // move center one quarter map width left var offsetY = 0.25; // move center one quarter map height down var span = map.getBounds().toSpan(); // a latLng - # of deg map spans var newCenter = { lat: center.lat() + span.lat()*offsetY, lng: center.lng() + span.lng()*offsetX }; map.panTo(newCenter); // or map.setCenter(newCenter); 

下面是使用maps API的panBy()方法解决问题的示例: http : //jsfiddle.net/upsidown/2wej9smf/

安德鲁是答案。 但是,在我的情况下,map.getBounds()保持返回undefined。 我修正了它等待bounds_changed事件, 然后调用函数来抵消中心。 像这样:

 var center_moved = false; google.maps.event.addListener(map, 'bounds_changed', function() { if(!center_moved){ offsetCenter(map.getCenter(), 250, -200); center_moved = true; } }); 

经过广泛的search,我无法find一种方法来做到这一点,也包括缩放。 幸好一个聪明的小伙子已经知道了。 这里也有一个小提琴

 'use strict'; const TILE_SIZE = { height: 256, width: 256 }; // google World tile size, as of v3.22 const ZOOM_MAX = 21; // max google maps zoom level, as of v3.22 const BUFFER = 15; // edge buffer for fitting markers within viewport bounds const mapOptions = { zoom: 14, center: { lat: 34.075328, lng: -118.330432 }, options: { mapTypeControl: false } }; const markers = []; const mapDimensions = {}; const mapOffset = { x: 0, y: 0 }; const mapEl = document.getElementById('gmap'); const overlayEl = document.getElementById('overlay'); const gmap = new google.maps.Map(mapEl, mapOptions); const updateMapDimensions = () => { mapDimensions.height = mapEl.offsetHeight; mapDimensions.width = mapEl.offsetWidth; }; const getBoundsZoomLevel = (bounds, dimensions) => { const latRadian = lat => { let sin = Math.sin(lat * Math.PI / 180); let radX2 = Math.log((1 + sin) / (1 - sin)) / 2; return Math.max(Math.min(radX2, Math.PI), -Math.PI) / 2; }; const zoom = (mapPx, worldPx, fraction) => { return Math.floor(Math.log(mapPx / worldPx / fraction) / Math.LN2); }; const ne = bounds.getNorthEast(); const sw = bounds.getSouthWest(); const latFraction = (latRadian(ne.lat()) - latRadian(sw.lat())) / Math.PI; const lngDiff = ne.lng() - sw.lng(); const lngFraction = ((lngDiff < 0) ? (lngDiff + 360) : lngDiff) / 360; const latZoom = zoom(dimensions.height, TILE_SIZE.height, latFraction); const lngZoom = zoom(dimensions.width, TILE_SIZE.width, lngFraction); return Math.min(latZoom, lngZoom, ZOOM_MAX); }; const getBounds = locations => { let northeastLat; let northeastLong; let southwestLat; let southwestLong; locations.forEach(function(location) { if (!northeastLat) { northeastLat = southwestLat = location.lat; southwestLong = northeastLong = location.lng; return; } if (location.lat > northeastLat) northeastLat = location.lat; else if (location.lat < southwestLat) southwestLat = location.lat; if (location.lng < northeastLong) northeastLong = location.lng; else if (location.lng > southwestLong) southwestLong = location.lng; }); const northeast = new google.maps.LatLng(northeastLat, northeastLong); const southwest = new google.maps.LatLng(southwestLat, southwestLong); const bounds = new google.maps.LatLngBounds(); bounds.extend(northeast); bounds.extend(southwest); return bounds; }; const zoomWithOffset = shouldZoom => { const currentzoom = gmap.getZoom(); const newzoom = shouldZoom ? currentzoom + 1 : currentzoom - 1; const offset = { x: shouldZoom ? -mapOffset.x / 4 : mapOffset.x / 2, y: shouldZoom ? -mapOffset.y / 4 : mapOffset.y / 2 }; const newCenter = offsetLatLng(gmap.getCenter(), offset.x, offset.y); if (shouldZoom) { gmap.setZoom(newzoom); gmap.panTo(newCenter); } else { gmap.setCenter(newCenter); gmap.setZoom(newzoom); } }; const setMapBounds = locations => { updateMapDimensions(); const bounds = getBounds(locations); const dimensions = { width: mapDimensions.width - mapOffset.x - BUFFER * 2, height: mapDimensions.height - mapOffset.y - BUFFER * 2 }; const zoomLevel = getBoundsZoomLevel(bounds, dimensions); gmap.setZoom(zoomLevel); setOffsetCenter(bounds.getCenter()); }; const offsetLatLng = (latlng, offsetX, offsetY) => { offsetX = offsetX || 0; offsetY = offsetY || 0; const scale = Math.pow(2, gmap.getZoom()); const point = gmap.getProjection().fromLatLngToPoint(latlng); const pixelOffset = new google.maps.Point((offsetX / scale), (offsetY / scale)); const newPoint = new google.maps.Point( point.x - pixelOffset.x, point.y + pixelOffset.y ); return gmap.getProjection().fromPointToLatLng(newPoint); }; const setOffsetCenter = latlng => { const newCenterLatLng = offsetLatLng(latlng, mapOffset.x / 2, mapOffset.y / 2); gmap.panTo(newCenterLatLng); }; const locations = [{ name: 'Wilshire Country Club', lat: 34.077796, lng: -118.331151 }, { name: '301 N Rossmore Ave', lat: 34.077146, lng: -118.327805 }, { name: '5920 Beverly Blvd', lat: 34.070281, lng: -118.331831 }]; locations.forEach(function(location) { let marker = new google.maps.Marker({ position: new google.maps.LatLng(location.lat, location.lng), title: location.name }) marker.setMap(gmap); markers.push(marker); }); mapOffset.x = overlayEl.offsetWidth; document.zoom = bool => zoomWithOffset(bool); document.setBounds = () => setMapBounds(locations); 
 section { height: 180px; margin-bottom: 15px; font-family: sans-serif; color: grey; } figure { position: relative; margin: 0; width: 100%; height: 100%; } figcaption { position: absolute; left: 15px; top: 15px; width: 120px; padding: 15px; background: white; box-shadow: 0 2px 5px rgba(0, 0, 0, .3); } gmap { display: block; height: 100%; } 
 <script type="text/javascript" src="https://maps.googleapis.com/maps/api/js"></script> <section> <figure> <gmap id="gmap"></gmap> <figcaption id="overlay"> <h4>Tile Overlay</h4> <p>To be avoided by the map!</p> </figcaption> </figure> </section> <button onclick="zoom(true)">zoom in</button> <button onclick="zoom(false)">zoom out</button> <button onclick="setBounds()">set bounds</button> 

老问题,我知道。 但是更多的以CSS为中心的方式呢?

http://codepen.io/eddyblair/pen/VjpNQQ

我做的是:

这样地图的中心位于所需区域的中心。 js只是标准的地图js。

重新定位街景的图标是读者的一个练习:)


如果你想要在左边的覆盖,只要将第24margin-left margin-right和第32行从rightleft

当涉及到抵消路线或一组标记的另一种方法可以在这里find:

https://stackoverflow.com/a/26192440/1238965

它仍然使用@Andrew Leach回答中描述的fromLatLngToPoint()方法。