首页 文章

Google Maps API - maps.setCenter似乎并不以用户位置为中心

提问于
浏览
0

我一直在使用谷歌 Map API,有一件事特别困扰我 .

我在页面加载时设置了原始 Map ,然后一旦用户点击“登录”按钮并分享他们的位置,就会在上面的信息窗口中显示一系列“商店”,其中包含用户位置和商店之间的距离 . 标记 .

我在Firefox中遇到的问题是,商店阵列加载, Map 位于商店中间位置,而不是以用户位置为中心的 Map .

这里的一些变量只是暂时保留虚拟内容 .

当最后一个函数(addDabblerArrayToMap)运行时,它会检查'centerPos' - 保存用户位置的变量,然后执行一个或另一个操作:1 . 如果centerPos = null,则将标记添加到 Map 中,并且默认位置将被删除到 Map 上,而不会进行任何距离计算 . 2.如果centerPos持有lat&lng,则计算每个商店与用户之间的距离并将其附加到显示在相关商店标记上方的infoWindow,以便用户可以看到每个商店离他们的位置有多远 .

  • 运行时,map.setCenter(centerPos)不会将 Map 置于用户位置的中心位置 . 它将 Map 设置在商店阵列的中间 . 我可以进入浏览器控制台并键入'map.setCenter(centerPos)' - 然后它会将 Map 居中到用户位置 .

完整代码如下:

HTML:

<div id="map"></div>
<button onClick="runAllChainEvents();">Sign in</button>

CSS:

#map {
   height: 100%;
}

JS:

var neighborhoods = [
    {lat: -36.862338, lng: 174.7425013},
    {lat: -36.867204, lng: 174.7692113},
    {lat: -36.848362, lng: 174.7426733},
    {lat: -36.845028, lng: 174.7748043},
    {lat: -36.862644, lng: 174.7340973},
    {lat: -36.862775, lng: 174.7836023}
];
var markers =[];
var map;
var dabblers = "../favicon-32x32.png";
var yourLocation = "../dabble-icon.png";
var myLocationIconArray = [];
var hasHappened = false;
var infoWindowContentString = '';
var dabblerInfoWindow = null;
var addInfowindow;
var distanceArray = [];
var defaultPos = {lat: -36.8527785, lng: 174.7617562};
var centerPos;

var dabblersArray = [
    {lat: -36.862338, lng: 174.7425013, type: 'sweet'},
    {lat: -36.867204, lng: 174.7692113, type: 'sweet'},
    {lat: -36.848362, lng: 174.7426733, type: 'sweet'},
    {lat: -36.845028, lng: 174.7748043, type: 'savoury'},
    {lat: -36.862644, lng: 174.7340973, type: 'savoury'},
    {lat: -36.862775, lng: 174.7836023, type: 'savoury'}
];

/* Initializes map with custom styles, centers location, 
   and defines Map UI */
function initMap() {
    var customMapType = new google.maps.StyledMapType([
        {
          stylers: [
            {hue: '#8c8c8c'},
            {visibility: 'simplified'}
          ]
        },
        {
          elementType: 'labels',
          stylers: [{visibility: 'off'}]
        },
        {
          elementType: 'landscape',
          stylers: [{color: '#e6e6e6'}]
        },
        {
          featureType: 'road',
          stylers: [{color: '#ffffff'}]
        },
        {
          featureType: 'road.highway.controlled_access',
          stylers: [{color: '#cccccc'}]
        },
        {
          featureType: 'road.arterial',
          stylers: [{color: '#cccccc'}]
        },
        {
          featureType: 'water',
          stylers: [
            {color: '#dce6e6'},
            {"lightness": -10},
            {"saturation": -30}
          ]
        },
        {
          featureType: 'poi',
          stylers: [{visibility: 'off'}]
        },
        {
          featureType: 'transit.line',
          stylers: [{visibility: 'off'}]
        }
    ], { name: 'Custom Style'
    });   
    var customMapTypeId = 'custom_style';
    map = new google.maps.Map(document.getElementById('map'), {
          center: { lat: -36.8527785, lng: 174.7617562}, // Auckland City coords
          zoom: 15,
          disableDefaultUI: true,
          zoomControl: false,
          mapTypeControl: false,
          scaleControl: false,
          fullscreenControl: false,
          streetViewControl: false,
          mapTypeControlOptions: {
            mapTypeIds: [google.maps.MapTypeId.ROADMAP, customMapTypeId]
          }
    });
    map.mapTypes.set(customMapTypeId, customMapType);
    map.setMapTypeId(customMapTypeId);
    map.setOptions({draggable: false, zoomControl: false,
    zoomControlOptions: {
              position: google.maps.ControlPosition.BOTTOM_CENTER
          },
    scrollwheel: false, disableDoubleClickZoom: true});
    drop();
}

/* Takes positions in neighborhoodsArray and runs each through 
   the addMarkerWithTimeout function */
function drop() {
  var delay = 800;
    for (var i = 0; i < neighborhoods.length; i++) {
      addMarkerWithTimeout(neighborhoods[i], i*200 + delay);
    }
}

/* Takes position (lat / long) and timeout parameters and converts 
   into Google Map Markers. Then adds to Google Map. */
function addMarkerWithTimeout(position, timeout) {
    window.setTimeout(function() {
      markers.push(new google.maps.Marker({
        position: position,
        map: map,
        animation: google.maps.Animation.DROP,
        icon: dabblers,
        draggable: false,
        clickable: false
      }));
    }, timeout);
}

/*  Clears original markers from map and sets relative arrays to [] */
function deleteMarkers() {
    for (var x = 0; x < markers.length; x++) {
      markers[x].setMap(null);
    }
    markers = [];
    neighborhoods = [];
}

/* Adds your location & infoWindow to map after signIn */   
function addMarker(location, addInfowindow) {
    var marker = new google.maps.Marker({
        position: location,
        map: map,
        animation: google.maps.Animation.DROP,
        icon: yourLocation,
        draggable: false,
        clickable: true
    });
    if (addInfowindow == null) {
        var myLocationInfowindow = new google.maps.InfoWindow({
          content: "Your location"
        });
        myLocationInfowindow.open(map, marker);
        myLocationIconArray.push(marker);
    } else {
        var myLocationInfowindow = new google.maps.InfoWindow({
          content: infoWindowContentString
        });
        myLocationInfowindow.open(map, marker);
        myLocationIconArray.push(marker);
    }
}

/* Checks if Users browser / device is capable of Geolocation. If it is, gets current position */
function getUserLocation(onComplete) {  
    map.setOptions({draggable: true, zoomControl: true, scrollwheel: true, disableDoubleClickZoom: false});

    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(function(position) {
            centerPos = {
                lat: position.coords.latitude,
                lng: position.coords.longitude
            };
            map.setCenter(centerPos);
            addMarker(centerPos);
            onComplete();
        }, function() {
            handleLocationError(true, addInfowindow, map.getCenter());
        });
    } else {
        //Browser doesn't support Geolocation
        handleLocationError(false, addInfowindow, map.getCenter());
    }
}

/* Removes elements, and adds Dabblers to map */
function runAllChainEvents() {
    getUserLocation(addDabblerArrayToMap);
}

/* Handles error if Users browser / device is not capable of Geolocation
   lookup functionality. Places their location at centre of Auckland. */    
function handleLocationError(browserHasGeolocation, addInfowindow, defaultPos) {
    if (browserHasGeolocation) {
        infoWindowContentString = "Sorry, we can't get your location."; 
    } else {
        infoWindowContentString = "Your current browser does not support Geolocation.";
    }
    addInfowindow = new google.maps.InfoWindow({
          content: infoWindowContentString
        });
    map.setCenter(defaultPos);
    addMarker(defaultPos, addInfowindow);
    addDabblerArrayToMap(null);
}

/* Takes positions in dabblersArray and runs each through 
   the addMarkerWithTimeout function. Then calculates the 
   distance between user and dabblers.   */
function addDabblerArrayToMap(position1) {
    var distance;
    var dabblerLocation;
    deleteMarkers();
    position1 = centerPos;

    if (position1 == null) {
        for (var z = 0; z < dabblersArray.length; z++) {
            markers.push(new google.maps.Marker({
            position: { lat: dabblersArray[z].lat, lng: dabblersArray[z].lng},
            map: map,
            icon: dabblers,
            draggable: false,
            clickable: true,
            id: dabblersArray[z].type
            }));
        }
    } else {
        var usersPosition = new google.maps.LatLng(centerPos.lat, centerPos.lng);

        for (var y = 0; y < dabblersArray.length; y++) {    
            dabblerLocation = new google.maps.LatLng(dabblersArray[y].lat, dabblersArray[y].lng);

            distance = google.maps.geometry.spherical.computeDistanceBetween(usersPosition, dabblerLocation);
            distance = parseFloat(distance / 1000).toFixed(2);
            distanceArray.push(distance);

            dabblerInfoWindow = new google.maps.InfoWindow({
                content: distance + "km"
            });

            markers.push(new google.maps.Marker({
            position: { lat: dabblersArray[y].lat, lng: dabblersArray[y].lng },
                map: map,
                icon: dabblers,
                draggable: false,
                clickable: true,
                id: dabblersArray[y].type
            }));
            dabblerInfoWindow.open(map, markers[y]);
        }
    // I shouldn't need to add this here, but have tried to set Center
       position manually again here to no avail also.
    map.setCenter(centerPos);
    }
}

1 回答

  • 2

    问题是你正在做的事情 . map.setCenter 到用户的位置在 addMarkerWithTimeout 呼叫超时之前运行 . 当这些标记添加到 Map 中时,它们的信息窗口会打开,使 Map 居中以显示最后打开的信息窗口 .

    修复此问题的一个选项是在infowindows上设置 disableAutoPan: true .

    proof of concept fiddle

    code snippet:

    var neighborhoods = [{
      lat: -36.862338,
      lng: 174.7425013
    }, {
      lat: -36.867204,
      lng: 174.7692113
    }, {
      lat: -36.848362,
      lng: 174.7426733
    }, {
      lat: -36.845028,
      lng: 174.7748043
    }, {
      lat: -36.862644,
      lng: 174.7340973
    }, {
      lat: -36.862775,
      lng: 174.7836023
    }];
    var markers = [];
    var map;
    var dabblers = "https://maps.google.com/mapfiles/ms/micons/blue.png";
    var yourLocation = "https://maps.google.com/mapfiles/ms/micons/red.png";
    var myLocationIconArray = [];
    var hasHappened = false;
    var infoWindowContentString = '';
    var dabblerInfoWindow = null;
    var addInfowindow;
    var distanceArray = [];
    var defaultPos = {
      lat: -36.8527785,
      lng: 174.7617562
    };
    var centerPos;
    
    var dabblersArray = [{
      lat: -36.862338,
      lng: 174.7425013,
      type: 'sweet'
    }, {
      lat: -36.867204,
      lng: 174.7692113,
      type: 'sweet'
    }, {
      lat: -36.848362,
      lng: 174.7426733,
      type: 'sweet'
    }, {
      lat: -36.845028,
      lng: 174.7748043,
      type: 'savoury'
    }, {
      lat: -36.862644,
      lng: 174.7340973,
      type: 'savoury'
    }, {
      lat: -36.862775,
      lng: 174.7836023,
      type: 'savoury'
    }];
    
    /* Initializes map with custom styles, centers location, 
       and defines Map UI */
    function initMap() {
      var customMapType = new google.maps.StyledMapType([{
        stylers: [{
          hue: '#8c8c8c'
        }, {
          visibility: 'simplified'
        }]
      }, {
        elementType: 'labels',
        stylers: [{
          visibility: 'off'
        }]
      }, {
        elementType: 'landscape',
        stylers: [{
          color: '#e6e6e6'
        }]
      }, {
        featureType: 'road',
        stylers: [{
          color: '#ffffff'
        }]
      }, {
        featureType: 'road.highway.controlled_access',
        stylers: [{
          color: '#cccccc'
        }]
      }, {
        featureType: 'road.arterial',
        stylers: [{
          color: '#cccccc'
        }]
      }, {
        featureType: 'water',
        stylers: [{
          color: '#dce6e6'
        }, {
          "lightness": -10
        }, {
          "saturation": -30
        }]
      }, {
        featureType: 'poi',
        stylers: [{
          visibility: 'off'
        }]
      }, {
        featureType: 'transit.line',
        stylers: [{
          visibility: 'off'
        }]
      }], {
        name: 'Custom Style'
      });
      var customMapTypeId = 'custom_style';
      map = new google.maps.Map(document.getElementById('map'), {
        center: {
          lat: -36.8527785,
          lng: 174.7617562
        }, // Auckland City coords
        zoom: 15,
        disableDefaultUI: true,
        zoomControl: false,
        mapTypeControl: false,
        scaleControl: false,
        fullscreenControl: false,
        streetViewControl: false,
        mapTypeControlOptions: {
          mapTypeIds: [google.maps.MapTypeId.ROADMAP, customMapTypeId]
        }
      });
      map.mapTypes.set(customMapTypeId, customMapType);
      map.setMapTypeId(customMapTypeId);
      map.setOptions({
        draggable: false,
        zoomControl: false,
        zoomControlOptions: {
          position: google.maps.ControlPosition.BOTTOM_CENTER
        },
        scrollwheel: false,
        disableDoubleClickZoom: true
      });
      drop();
    }
    
    /* Takes positions in neighborhoodsArray and runs each through 
       the addMarkerWithTimeout function */
    function drop() {
      var delay = 800;
      for (var i = 0; i < neighborhoods.length; i++) {
        addMarkerWithTimeout(neighborhoods[i], i * 200 + delay);
      }
    }
    
    /* Takes position (lat / long) and timeout parameters and converts 
       into Google Map Markers. Then adds to Google Map. */
    function addMarkerWithTimeout(position, timeout) {
      window.setTimeout(function() {
        markers.push(new google.maps.Marker({
          position: position,
          map: map,
          animation: google.maps.Animation.DROP,
          icon: dabblers,
          draggable: false,
          clickable: false
        }));
      }, timeout);
    }
    
    /*  Clears original markers from map and sets relative arrays to [] */
    function deleteMarkers() {
      for (var x = 0; x < markers.length; x++) {
        markers[x].setMap(null);
      }
      markers = [];
      neighborhoods = [];
    }
    
    /* Adds your location & infoWindow to map after signIn */
    function addMarker(location, addInfowindow) {
      var marker = new google.maps.Marker({
        position: location,
        map: map,
        animation: google.maps.Animation.DROP,
        icon: yourLocation,
        draggable: false,
        clickable: true
      });
      if (addInfowindow == null) {
        var myLocationInfowindow = new google.maps.InfoWindow({
          content: "Your location",
          disableAutoPan: false
        });
        myLocationInfowindow.open(map, marker);
        myLocationIconArray.push(marker);
      } else {
        var myLocationInfowindow = new google.maps.InfoWindow({
          content: infoWindowContentString,
          disableAutoPan: true
        });
        myLocationInfowindow.open(map, marker);
        myLocationIconArray.push(marker);
      }
    }
    
    /* Checks if Users browser / device is capable of Geolocation. If it is, gets current position */
    function getUserLocation(onComplete) {
      map.setOptions({
        draggable: true,
        zoomControl: true,
        scrollwheel: true,
        disableDoubleClickZoom: false
      });
    
      if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(function(position) {
          centerPos = {
            lat: position.coords.latitude,
            lng: position.coords.longitude
          };
          map.setCenter(centerPos);
          addMarker(centerPos);
          onComplete();
        }, function() {
          handleLocationError(true, addInfowindow, map.getCenter());
        });
      } else {
        //Browser doesn't support Geolocation
        handleLocationError(false, addInfowindow, map.getCenter());
      }
    }
    
    /* Removes elements, and adds Dabblers to map */
    function runAllChainEvents() {
      getUserLocation(addDabblerArrayToMap);
    }
    
    /* Handles error if Users browser / device is not capable of Geolocation
       lookup functionality. Places their location at centre of Auckland. */
    function handleLocationError(browserHasGeolocation, addInfowindow, defaultPos) {
      if (browserHasGeolocation) {
        infoWindowContentString = "Sorry, we can't get your location.";
      } else {
        infoWindowContentString = "Your current browser does not support Geolocation.";
      }
      addInfowindow = new google.maps.InfoWindow({
        content: infoWindowContentString,
        disableAutoPan: true
      });
      map.setCenter(defaultPos);
      addMarker(defaultPos, addInfowindow);
      addDabblerArrayToMap(null);
    }
    
    /* Takes positions in dabblersArray and runs each through 
       the addMarkerWithTimeout function. Then calculates the 
       distance between user and dabblers.   */
    function addDabblerArrayToMap(position1) {
      var distance;
      var dabblerLocation;
      deleteMarkers();
      position1 = centerPos;
    
      if (position1 == null) {
        for (var z = 0; z < dabblersArray.length; z++) {
          markers.push(new google.maps.Marker({
            position: {
              lat: dabblersArray[z].lat,
              lng: dabblersArray[z].lng
            },
            map: map,
            icon: dabblers,
            draggable: false,
            clickable: true,
            id: dabblersArray[z].type
          }));
        }
      } else {
        var usersPosition = new google.maps.LatLng(centerPos.lat, centerPos.lng);
    
        for (var y = 0; y < dabblersArray.length; y++) {
          dabblerLocation = new google.maps.LatLng(dabblersArray[y].lat, dabblersArray[y].lng);
    
          distance = google.maps.geometry.spherical.computeDistanceBetween(usersPosition, dabblerLocation);
          distance = parseFloat(distance / 1000).toFixed(2);
          distanceArray.push(distance);
    
          dabblerInfoWindow = new google.maps.InfoWindow({
            content: distance + "km",
            disableAutoPan: true
          });
    
          markers.push(new google.maps.Marker({
            position: {
              lat: dabblersArray[y].lat,
              lng: dabblersArray[y].lng
            },
            map: map,
            icon: dabblers,
            draggable: false,
            clickable: true,
            id: dabblersArray[y].type
          }));
          dabblerInfoWindow.open(map, markers[y]);
        }
        // I shouldn't need to add this here, but have tried to set Center
        //    position manually again here to no avail also.
        // setTimeout(function() {
        map.setCenter(centerPos)
          //}, 5000);
      }
    }
    google.maps.event.addDomListener(window, "load", initMap);
    
    html,
    body {
      height: 100%;
    }
    #map {
      height: 90%;
    }
    
    <script src="https://maps.googleapis.com/maps/api/js?libraries=geometry"></script>
    <div id="map"></div>
    <button onClick="runAllChainEvents();">Sign in</button>
    

相关问题