Is there a way to Fix a Google Maps Marker to the

2019-01-08 11:23发布

问题:

To be more precise, what I try to accomplish is that while I Drag a Google Map there's a Google Maps Marker that stays fixed at the center of the map at all times. This will improve User experience in my opinion, This is how I'm doing it now:

var map, marker, options;

options = {
  center: new google.maps.LatLng(latitude, longitude),
  zoom: 15,
  mapTypeId: google.maps.MapTypeId.ROADMAP,
  mapTypeControl: false,
  overviewMapControl: false,
  zoomControl: true,
  draggable: true
};

map = new google.maps.Map(mapContainer, options);

marker = new google.maps.Marker({
  position: new google.maps.LatLng(latitude, longitude),
  map: map,
  animation: google.maps.Animation.DROP
});

//This line is what makes the Marker stick to the center of the map
marker.bindTo('position', map, 'center');

The problem I have with the code above is that.. When I drag the map underneath the Marker it's not smooth enough, ie. the Marker makes a wierd jump from the 'last' center to the 'new' center when dragging ends. (this is more noticeable on mobile devices), Therefore what I need is that the Marker is Really permanently fixed to the Center of its Map.

Is there a way to get this done? (I think I've seen this in a web-site once)

Let me know If you guys can help me.

Thank you.

回答1:

A different approach, that did not use a real google.maps.Marker:

after the map has been initialized, inject a div into the map-container, give it a className(e.g. centerMarker), the further things will be done via CSS:

.centerMarker{
  position:absolute;
  /*url of the marker*/
  background:url(http://maps.gstatic.com/mapfiles/markers2/marker.png) no-repeat;
  /*center the marker*/
  top:50%;left:50%;

  z-index:1;
  /*fix offset when needed*/
  margin-left:-10px;
  margin-top:-34px;
  /*size of the image*/
  height:34px;
  width:20px;

  cursor:pointer;
}

Demo: http://jsfiddle.net/doktormolle/jcHqt/



回答2:

Rather than injecting an HTML component as suggested in @Dr.Molle's answer, why don't you use a CSS only solution.

It is simpler, more efficient and doesn't require you to even touch the DOM (so there won't be any problems if Google changes their implementation).

Also since Google Maps don't apply any styles on the container element (#map) the solution is pretty safe.

#map {
    position: relative;
}

#map:after {
    width: 22px;
    height: 40px;
    display: block;
    content: ' ';
    position: absolute;
    top: 50%; left: 50%;
    margin: -40px 0 0 -11px;
    background: url('https://maps.gstatic.com/mapfiles/api-3/images/spotlight-poi_hdpi.png');
    background-size: 22px 40px; /* Since I used the HiDPI marker version this compensates for the 2x size */
    pointer-events: none; /* This disables clicks on the marker. Not fully supported by all major browsers, though */
}

Here is a jsFiddle.



回答3:

You can listen to the center changes via something like below, you will just have to update your view:

google.maps.event.addListener(map, "dragend", function() {
   console.log(map.getCenter().toUrlValue());
});

Current main used solution is for bringing up the InfoWindow only when onclick, I needed it on all the time like it is on Uber, so I replaced even the InfoWindow to a css only solution, updating the view the normal angular route with Ionic

HTML:

 <ion-content >
   <div id="map" data-tap-disabled="true">
  </div>
  <div id="centerInfoBubble">
    <span>{{locationCtrl.coordinates}}</span>
  </div>
  <div id="centerMarker"></div>
 </div>
 </ion-content>

CSS:

#map {
 width: 100%;
 height: 100%;
}
#centerInfoBubble {
  position: absolute;
  /*center the marker*/
 top: 38%;
 left: 22.5%;
 z-index: 1;
 width: 50%;
 height: 6%;
 border-radius: 20px;
 border: 1px solid #111;
 background-color: #444444;
 color: #fff;
 padding: 0.5% 5%;
 cursor: pointer;
}
#centerMarker {
 position: absolute;
 /*url of the marker*/
 background: url(http://maps.gstatic.com/mapfiles/markers2/marker.png) no-repeat;
 /*center the marker*/
 top: 45%;
 left: 45%;
 z-index: 1;
 height: 10%;
 width: 10%;
 cursor: pointer;
}

Controller:

myModule.controller('LocationCtrl',['$scope','$cordovaGeolocation',function($scope,$cordovaGeolocation){
$scope.locationCtrl = {
    coordinates : null
};
var options = {timeout: 10000, enableHighAccuracy: true};
var marker;

$cordovaGeolocation.getCurrentPosition(options).then(function(position){

    var latLng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);

    var mapOptions = {
            center : latLng,
            zoom : 16,
            mapTypeId : google.maps.MapTypeId.ROADMAP,
            mapTypeControl : false,
            streetViewControl : false,
            zoomControl : false
    };

    $scope.map = new google.maps.Map(document.getElementById("map"), mapOptions);
    $scope.locationCtrl.coordinates = $scope.map.getCenter().toUrlValue();

    google.maps.event.addListener($scope.map, "dragend", function() {
        $scope.locationCtrl.coordinates = $scope.map.getCenter().toUrlValue();
        $scope.$apply();
    });

}, function(error){
console.log("Could not get location");
});

}]);

I don't know if there are performance issues with this yet, but looks quite smooth on the device, hope it helps someone



回答4:

If this can help, what I did is :

const myLatLng = {lat: 42, lng: 42};

map = new google.maps.Map(document.getElementById('map'), {
  center: myLatLng,
  zoom: 14,
});

marker = new google.maps.Marker({
  position: myLatLng,
  map: map,
});

map.addListener('center_changed', () => {
  marker.setPosition(map.getCenter())
})


回答5:

You can use google map drag event:

google.maps.event.addListener(map, 'dragend', function() {
    marker.setPosition(map.getCenter()); 
} );