Ich habe eine Google-Karte mit einem halbtransparenten Bereich, der einen Teil des Gebiets abdeckt. Ich möchte den Mittelpunkt der Karte anpassen, um den Teil der Karte zu berücksichtigen, der teilweise verdeckt ist. Siehe das Bild unten. Idealerweise ist der Mittelpunkt der Karte der Ort, an dem das Fadenkreuz und der Stift platziert sind.
Ich hoffe das ergibt Sinn.
Der Grund ist einfach: Wenn Sie zoomen, muss die Karte über dem Fadenkreuz zentriert werden und nicht bei 50% bis 50%. Außerdem werde ich Markierungen auf der Karte zeichnen und sie nacheinander durchlaufen. Wenn die Karte auf sie zentriert ist, müssen sie sich auch an der versetzten Position befinden.
Danke im Voraus!
javascript
google-maps-api-3
werden
quelle
quelle
Antworten:
Dies ist nicht besonders schwierig, wenn Sie die entsprechende vorherige Antwort gefunden haben .
Sie müssen die Mitte der Karte in ihre Weltkoordinaten konvertieren, herausfinden, wo die Karte zentriert werden muss, um die scheinbare Mitte an die gewünschte Stelle zu bringen, und die Karte mithilfe der realen Mitte neu zentrieren .
Die API zentriert die Karte immer in der Mitte des Ansichtsfensters. Sie müssen also vorsichtig sein, wenn Sie sie verwenden,
map.getCenter()
da sie das reale Zentrum und nicht das scheinbare Zentrum zurückgibt. Ich nehme an, es wäre möglich, die API zu überladen, so dass ihregetCenter()
undsetCenter()
Methoden ersetzt werden, aber das habe ich nicht getan.Code unten. Beispiel online . Im Beispiel wird durch Klicken auf die Schaltfläche die Mitte der Karte (dort befindet sich eine Straßenkreuzung) um 100 Pixel nach unten und um 200 Pixel nach links verschoben.
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); }
quelle
map.setCenter()
. Alles, was dieser Code tut, ist neu zu berechnen, was die Karte tun soll, und dann macht es sein eigenesmap.setCenter()
.map.panBy(250, 0);
nw
Variable von diesem Skript nie verwendet wird und zumindest in meinem Anwendungsfall ohne Probleme entfernt werden kann. Ich habe das aber nicht alleine versucht, da ich bereits eine Reihe anderer Methoden habe, die die Grenzen setzen und so weiter.Schauen Sie sich auch die Funktion panBy (x: Nummer, y: Nummer) für das Kartenobjekt an.
In der Dokumentation wird Folgendes über die Funktion erwähnt:
Verwenden Sie es einfach so:
mapsObject.panBy(200, 100)
quelle
Hier ist eine einfachere Methode, die beim reaktionsschnellen Design möglicherweise nützlicher ist, da Sie Prozentsätze anstelle von Pixeln verwenden können. Keine Weltkoordinaten, keine LatLngs to Points!
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);
quelle
Hier ist ein Beispiel für die Lösung des Problems mithilfe der
panBy()
Methode der Karten-API: http://jsfiddle.net/upsidown/2wej9smf/quelle
Habe gerade eine andere einfachste Lösung gefunden. Wenn Sie die fitBounds-Methode verwenden, können Sie ihr optionales zweites Argument übergeben. Dieses Argument ist Auffüllen, das beim Anpassen von Grenzen berücksichtigt wird.
// pass single side: map.fitBounds(bounds, { left: 1000 }) // OR use Number: map.fitBounds(bounds, 20)
Weiterführende Literatur: offizielle Dokumente .
quelle
Andrews ist die Antwort. In meinem Fall gab map.getBounds () jedoch immer wieder undefiniert zurück. Ich habe das Warten auf das Ereignis bounds_changed behoben und dann die Funktion aufgerufen, um die Mitte zu versetzen. Wie so:
var center_moved = false; google.maps.event.addListener(map, 'bounds_changed', function() { if(!center_moved){ offsetCenter(map.getCenter(), 250, -200); center_moved = true; } });
quelle
Alte Frage, ich weiß. Aber wie wäre es mit einer CSS-zentrierteren Methode?
http://codepen.io/eddyblair/pen/VjpNQQ
Was ich getan habe war:
Wickeln Sie die Karte ein und überlagern Sie sie mit
overflow: hidden
Überlagert die Überlagerung mit
position: absolute
Erweitern Sie die scheinbare Breite der Karte um die Überlagerungsbreite (plus Auffüllen und Versatz), indem Sie ein Negativ festlegen
margin-left
.Um dann https://www.google.com/permissions/geoguidelines/attr-guide.html einzuhalten, positionierten Sie die Widgets und Zuordnungen
div
.Auf diese Weise liegt die Mitte der Karte in einer Linie mit der Mitte des gewünschten Bereichs. Das js ist nur eine Standardkarte js.
Das Neupositionieren der Symbole für Street View ist eine Übung für den Leser :)
Wenn Sie die Überlagerung links möchten, ändern Sie einfach Zeile
24
margin-left
zumargin-right
und Zeile 32right
zuleft
.quelle
Nach ausgiebiger Suche konnte ich keinen Weg finden, dies auch mit Zoom zu tun. Zum Glück hat ein kluger Kerl es herausgefunden. Hier gibt es auch eine Geige
'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>
quelle
Ein weiterer Ansatz zum Versetzen einer Route oder einer Gruppe von Markierungen finden Sie hier:
https://stackoverflow.com/a/26192440/1238965
Es wird weiterhin die
fromLatLngToPoint()
in der Antwort von @Andrew Leach beschriebene Methode verwendet .quelle