javascript - Google Maps API -maps.setCenter 似乎没有以用户位置为中心

标签 javascript google-maps google-maps-api-3

我一直在使用 Google Maps API,有件事特别困扰我。

我在页面加载时设置原始 map ,然后一旦用户单击“登录”按钮并共享他们的位置,就会在一个“商店”数组中显示用户位置和商店之间计算出的距离。标记上方的信息窗口。

我在 Firefox 中遇到的问题是,商店数组加载后, map 以商店位置的中间为中心,而不是以用户位置为中心的 map 。

这里的一些变量目前仅保存虚拟内容。

当最后一个函数 (addDabblerArrayToMap) 运行时,它会检查“centerPos”——保存用户位置的变量,然后执行一个或另一个操作: 1. 如果 centerPos = null,则标记将添加到 map 上,并将默认位置拖放到 map 上,而不进行任何距离计算。 2. 如果 centerPos 包含纬度和经度,则计算每个商店和用户之间的距离并将其附加到显示在相关商店标记上方的信息窗口,以便用户可以看到每个商店距其位置有多远。

  • 运行时,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);
    }
}

最佳答案

问题在于你做事的顺序。用户位置的 map.setCenteraddMarkerWithTimeout 调用超时之前运行。当这些标记添加到 map 中时,它们的信息窗口将打开,从而使 map 居中以显示最后打开的信息窗口。

解决此问题的一个选项是在信息窗口上设置 disableAutoPan: true

proof of concept fiddle

代码片段:

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>

关于javascript - Google Maps API -maps.setCenter 似乎没有以用户位置为中心,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39450281/

相关文章:

asp.net - 解析来自磁条的信用卡输入

c# - 彼此靠近的 Lat、Long 簇

google-maps-api-3 - 以编程方式关闭街景

javascript - 使用 CSS3 动画的 JavaScript 中的横幅旋转

javascript - JS 类 : avoiding manually assigning class variables

javascript - 在不同的 .env 文件中设置 PUBLIC_URL (create-react-app)

java - 在 fragment 选项卡中添加 map 时出错

java - 我在 android studio 中的位置有问题

javascript - 如何从 sap ui5 js View 中的构造函数对象接收属性值

google-maps-api-3 - Google 地理编码 API - 印度保留地