有没有一种方法可以始终将Google地图标记固定在其地图中心?

41
更确切地说,我试图在拖动谷歌地图时,让一个谷歌地图标记固定在地图中心位置,始终不变。这样做会改善用户体验。目前我的实现方式如下:
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');
我对上述代码的问题在于... 当我将地图在标记下方拖动时,它不够平滑,即当拖动结束时,标记从“上一个”中心跳到“新”的中心并出现了奇怪的跳跃(这在移动设备上更为明显)。因此,我需要的是Marker真正永久固定在其地图的中心。
有没有办法实现这个功能?(我想我曾在某个网站上看到过)
如果您能帮忙,请告诉我。
谢谢。

先生,抱歉,我在阅读文档后能想到的唯一解决方案就是您所看到的那个。如果您能教我如何实现您所描述的内容,我将不胜感激。 - jlstr
1
是的。并且它对我有效。它对你不起作用吗? - geocodezip
好的,请您在手机上试一下,如果拖动地图时没有出现任何奇怪的“跳跃”,请告诉我 :) 因为这就是问题所在。在台式机/笔记本电脑上似乎没有明显的问题。感谢您的回复,先生! - jlstr
你看过这篇文章吗?它是从这个群组的帖子中发现的。 - geocodezip
1
标记不是跳到@geocodezip给出的链接上了吗? - Rishabh Agrawal
显示剩余4条评论
7个回答

50

与其按照@Dr.Molle的回答建议注入HTML组件,为什么不使用只有CSS的解决方案呢。

它更简单、更高效,甚至不需要你接触DOM (因此如果Google改变了他们的实现方式,就不会出现任何问题)

另外,由于Google Maps不会对容器元素(#map)应用任何样式,所以这个解决方案非常安全。

#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 */
}

这里是一个jsFiddle


4
聪明的纯CSS解决方案!从未想过以这种方式使用CSS伪元素。谢谢。 - tamakisquare
3
更好的方法。我对注入方法感到不舒服,特别是因为它使用了JQuery。很高兴我往下滚动并找到了您的答案。 - Chris Redford

42

另一种方法是不使用真正的google.maps.Marker:

在地图初始化后,将一个div注入到地图容器中,并给它一个className(例如centerMarker),接下来的操作将通过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;
}

演示: http://jsfiddle.net/doktormolle/jcHqt/


看起来很不错。我会尽快试试,谢谢您,先生。这似乎正是我需要的东西。请等待。 - jlstr
1
很好的回答,但是当我们移动地图时,是否可能自动加载地图?还有一个问题,我们能否在拖动地图到新位置后获取该位置的坐标? - Vijay Shegokar
4
这不会帮助你获取纬度和经度。结合 map.addListener('center_changed', callback() {}) 的方法,也可以获得坐标。请进行尝试。 - Rishul Matta
很好的答案,这正是我在寻找的,但我想用我的自定义标记替换它,该怎么做呢?因为当我尝试替换它时,它就消失了,请帮忙。 - Alfred Alfizo Mosima
1
@Alfred Alfizo Mosima:没有看到你的尝试,很难帮助你。你可能需要修改CSS的宽度/高度/顶部/左侧。例如,使用你的头像(328x328像素)http://jsfiddle.net/doktormolle/0fmdasrg/ - Dr.Molle

8
您可以通过类似以下方式监听中心变化,您只需要更新您的视图即可:
google.maps.event.addListener(map, "dragend", function() {
   console.log(map.getCenter().toUrlValue());
});

目前主要使用的解决方案是仅在onclick时弹出InfoWindow,我需要像Uber一样始终处于打开状态,因此我甚至用纯CSS解决方案替换了InfoWindow,在Ionic中使用普通的Angular路由更新视图

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;
}

控制器:

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");
});

}]);

我不知道这是否存在性能问题,但在设备上看起来非常流畅,希望对某些人有所帮助


1
我会把所有控制器相关的内容放在服务或工厂中,具体取决于你的 Angular 方法,我将其放在一个服务中,包装在一个初始化函数中,然后使用 $timeout 在控制器中调用服务的初始化函数来进行控制器初始化。 - Mahlatse Makalancheche

6

如果这有所帮助,我做的是:

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())
})

2
这是一个不错的解决方案,因为它允许轮事件传播到地图,但它存在滞后问题,并且拖动时标记会跳跃和震动。 - Ali Sheikhpour

1

我在这里添加了带有固定针的地理位置按钮地图,以准确显示您的位置。

试试吧 :)

 
function loadScript(src,callback)
{ 
    var script = document.createElement("script");
    script.type = "text/javascript";
    if(callback)script.onload=callback;
    document.getElementsByTagName("head")[0].appendChild(script);
    script.src = src;
}
  
  loadScript('https://maps.googleapis.com/maps/api/js?v=3&sensor=false&callback=initialize');

function initialize() 
  {   
    map = new google.maps.Map(document.getElementById('map_canvas'), {
          zoom: 13, 
        });
latitudeTxt=document.getElementById('latitude');
longitudeTxt=document.getElementById('longitude');
        marker = new google.maps.Marker({
          map: map,
          draggable: false,
          animation: google.maps.Animation.DROP,
          position: {lat: 59.327, lng: 18.067}
        });
        var position = marker.getPosition();
        if(typeof position !== 'undefined')
        {
            map.setCenter(marker.getPosition());
        }
    
       map.addListener('center_changed', () => {
          
           marker.setPosition(map.getCenter())
            //get current location when we move the map 
            var NewMapCenter = map.getCenter();
           var latitude = NewMapCenter.lat();
     var longitude = NewMapCenter.lng();
           latitudeTxt.innerHTML =latitude;
           longitudeTxt.innerHTML =longitude;
        })
        
        addYourLocationButton(map, marker);
  }

 function geolocate() 
    {
        if (navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(function(position) {
            var geolocation = {
                lat: position.coords.latitude,
                lng: position.coords.longitude
            };
            map.setCenter(geolocation); 
            });
        }
    }
 
 function addYourLocationButton (map, marker) 
{
    var controlDiv = document.createElement('div');

    var firstChild = document.createElement('button');
    firstChild.style.backgroundColor = '#fff';
    firstChild.style.border = 'none';
    firstChild.style.outline = 'none';
    firstChild.style.width = '28px';
    firstChild.style.height = '28px';
    firstChild.style.borderRadius = '2px';
    firstChild.style.boxShadow = '0 1px 4px rgba(0,0,0,0.3)';
    firstChild.style.cursor = 'pointer';
    firstChild.style.marginRight = '10px';
    firstChild.style.padding = '0';
    firstChild.title = 'Your Location';
    controlDiv.appendChild(firstChild);

    var secondChild = document.createElement('div');
    secondChild.style.margin = '5px';
    secondChild.style.width = '18px';
    secondChild.style.height = '18px';
    secondChild.style.backgroundImage = 'url(https://maps.gstatic.com/tactile/mylocation/mylocation-sprite-2x.png)';
    secondChild.style.backgroundSize = '180px 18px';
    secondChild.style.backgroundPosition = '0 0';
    secondChild.style.backgroundRepeat = 'no-repeat';
    firstChild.appendChild(secondChild);

    google.maps.event.addListener(map, 'center_changed', function () {
        secondChild.style['background-position'] = '0 0';
    });

    firstChild.addEventListener('click', function () {
        var imgX = 0,
            animationInterval = setInterval(function () {
                imgX = -imgX - 18 ;
                secondChild.style['background-position'] = imgX+'px 0';
            }, 500);

        if(navigator.geolocation) {
            navigator.geolocation.getCurrentPosition(function(position) {
                var latlng = new google.maps.LatLng(position.coords.latitude, position.coords.longitude);
                map.setCenter(latlng);
                clearInterval(animationInterval);
                secondChild.style['background-position'] = '-144px 0';
            });
        } else {
            clearInterval(animationInterval);
            secondChild.style['background-position'] = '0 0';
        }
    });

    controlDiv.index = 1;
    map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(controlDiv);
}
body,html,#map_canvas{height:100%;margin:0;}
#map_canvas .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;
}
<html>
<body>
<div id="map_canvas" style="height:400px"></div>
<div id="latitude">latitude</div>
<br/>
<div id="longitude">longitude</div>
</body> 
</html>


0

您可以使用谷歌地图的拖动事件:

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

0

以下是如何尽可能顺畅地完成它,您还可以同时获取latlng。

    var map;
    var marker;
    var myInterval = setInterval(move, 1000 / 60);


    function handleEvent(event) {
        var latlng = map.getCenter();
        document.getElementById('lat').value = latlng.lat();
        document.getElementById('lng').value = latlng.lng();
    }



    // Initialize and add the map
    function initMap() {
        var uluru = { lat: -25.344, lng: 131.036 };
        map = new google.maps.Map(
            document.getElementById('map'), { zoom: 4, center: uluru });
        marker = new google.maps.Marker({
            position: uluru,
            map: map,
            animation: google.maps.Animation.DROP
        });
        map.addListener('center_changed', handleEvent);
        document.getElementById('lat').value = "-25.344";
        document.getElementById('lng').value = "131.036";
    }


    function move(){
        try {
          var latlngMAP = map.getCenter();
          var latlngMARKER = marker.getPosition();
          tempLAT = lerp (latlngMARKER.lat(), latlngMAP.lat(), 0.1);
          tempLNG = lerp (latlngMARKER.lng(), latlngMAP.lng(), 0.1);
         var latlng = { lat: tempLAT, lng: tempLNG };
          marker.setPosition(latlng);
        } catch{
        }
    }
    function lerp(start, end, amt) {
         return (1-amt)*start+amt*end
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接