Google Maps API v3 : fitBounds 후에 줌을 설정할 수 있습니까?


201

임베디드 Google Map (API v3)에 플롯하려는 점 세트가 있습니다. 확대 / 축소 수준이 너무 낮지 않으면 (즉, 너무 많이 축소하지 않는 한) 모든 점을 수용하기 위해 경계를 원합니다. 내 접근 방식은 다음과 같습니다.

var bounds = new google.maps.LatLngBounds();

// extend bounds with each point

gmap.fitBounds(bounds); 
gmap.setZoom( Math.max(6, gmap.getZoom()) );

작동하지 않습니다. 마지막 줄 "gmap.setZoom ()"은 fitBounds 바로 다음에 호출 된 경우 맵의 확대 / 축소 수준을 변경하지 않습니다.

지도에 적용하지 않고 범위의 확대 / 축소 수준을 얻는 방법이 있습니까? 이것을 해결할 다른 아이디어?


1
stackoverflow.com/questions/4523023/using-setzoom-after-using-fit-fits-with-google-maps-api-v3 참조
Mawg는 Monica를 복원합니다 Monica는

답변:


337

편집 : 아래 Matt Diamond의 의견을 참조하십시오.

알았다! 이 시도:

map.fitBounds(bounds);
var listener = google.maps.event.addListener(map, "idle", function() { 
  if (map.getZoom() > 16) map.setZoom(16); 
  google.maps.event.removeListener(listener); 
});

필요에 따라 수정하십시오.


76
훌륭한 솔루션, 완전히 나에게 많은 문제를 저장했습니다. addListenerOnce 메소드를 사용하여 더 단순화 할 수 있다고 덧붙이고 싶었습니다. 그러면 메소드가 자동으로 처리하므로 리스너를 저장하고 수동으로 제거 할 필요가 없습니다.
매트 다이아몬드

9
이것은 "건너 뛰기"맵을 보는 동작입니다. 대신 "zoom_change"이벤트를 수신하고 fitBounds ()를 호출하기 전에 설정하십시오. 내 대답은 아래를 참조
벤자민 서스

감사! google.maps.event.addListenerOnce (map, "idle", function () {}-> SugarCRM의지도 패키지에서 훌륭하게 작동했습니다.
jjwdesign

청취자가 나를 위해 트리거되지 않습니다. 나는 document.ready와 window.load에서 이것을 시도했다. 어떤 아이디어? map 객체는 정상이고 addListener도 시도했습니다 :`var map = $ ( "# js-main-map-canvas"); var listener = google.maps.event.addListenerOnce (map, "idle", function () {alert ( 'hello');});`
Henrik Erlandsson

Henrik, $ ( "# js-main-map-canvas") [0] 또는 $ ( "# js-main-map-canvas"). get (0);
라파엘

68

내 앱 중 하나에서 비슷한 문제를 해결했습니다. 나는 당신의 문제에 대한 당신의 설명에 약간 혼란 스러웠지만, 당신은 내가 가진 것과 같은 목표를 가지고 있다고 생각합니다 ...

내 응용 프로그램에서 하나 이상의 마커를 플롯하고 맵이 모두 표시되도록하고 싶었습니다. 문제는 내가 fitBounds 메소드에만 의존하면 단일 지점이있을 때 확대 / 축소 수준이 최대가 될 것입니다.

해결책은 포인트가 많을 때는 fitBounds를 사용하고 포인트가 하나만 있으면 setCenter + setZoom을 사용하는 것이 었습니다.

if (pointCount > 1) {
  map.fitBounds(mapBounds);
}
else if (pointCount == 1) {
  map.setCenter(mapBounds.getCenter());
  map.setZoom(14);
}

5
귀하의 답변으로 Google Maps V3의 문제가 해결되었습니다. 감사!
FR6

1
나는 똑같은 문제가 있었고 해결책이 효과가있었습니다! 감사!
manubkk

나는 같은 접근 방식을 직접 시도했지만 확대 / 축소를 설정하기 전에 setCenter ()를 호출하지 않았기 때문에 작동하지 않았습니다 ...이 단계가 왜 필요한지 궁금하지만 여전히 작동합니다 ... 감사합니다. 많은 짐!
daveoncode

지도 센터에서 발생한 문제를 해결했습니다! Nice one +1
Piotr Kula

1
좋은 답변 감사합니다 +1
Bharat Chodvadiya

44

답변을 얻기 위해이 페이지를 여러 번 방문했으며 기존의 모든 답변이 도움이되었지만 내 문제를 정확하게 해결하지 못했습니다.

google.maps.event.addListenerOnce(googleMap, 'zoom_changed', function() {
    var oldZoom = googleMap.getZoom();
    googleMap.setZoom(oldZoom - 1); //Or whatever
});

기본적으로 'zoom_changed'이벤트는지도의 UI가 '유휴'이벤트를 기다릴 때 발생하는 "건너 뛰기"를 방지한다는 것을 알았습니다.

이것이 누군가를 돕기를 바랍니다!


4
훌륭합니다. '건너 뛰기 / 자동 확대'동작도있었습니다. 다른 독자를위한 참고 사항 : Benjamin이 "addListener"대신 "addListenerOnce"를 사용하거나 브라우저가 항상 충돌하는 이유에 대해 머리를 아프게하십시오 ;-)
Geert-Jan

6
또한 다음을 fitBounds()사용 하는 경우 호출하기 전에 리스너를 추가해야합니다.zoom_changed
gapple

1
이것에 감사합니다, v4는 fitBounds (bounds, minZoomLevel) :)
Richard

3
벤자민, 나는 줌 레벨을 유지할 때 트리거 될 필요가 bounds_changed없기 때문에 사용하는 것이 낫다고 생각합니다 . 내 시도 jsfiddle.net/rHeMp/10 은 그것을 확인하지 않지만 정의되지 않은 행동에 의존해서는 안됩니다. zoom_changedfitBounds
TMS

10

maxZoom을 미리 설정 한 다음 나중에 제거하여이 문제를 해결했습니다. 예를 들면 다음과 같습니다.

map.setOptions({ maxZoom: 15 });
map.fitBounds(bounds);
map.setOptions({ maxZoom: null });

확대를 너무 많이 방지하는 최고의 솔루션입니다. 간단하고 직관적입니다. 지도 그리기 및 다시 그리기가 없습니다.
user2605793

이것은 실제로 지금까지 가장 좋은 방법입니다.
Downhillski

2
확대 / 축소가 비동기 적으로 발생하기 때문에 fitBounds를 호출 한 후 즉시 maxZoom을 재설정하면 이것이 작동하지 않는 것으로 나타났습니다. "유휴"가 재설정 될 때까지 기다리면이 문제가 해결 될 것입니다.
user987356

4

내가 실수하지 않으면 가능한 모든 줌 레벨로지도에 모든 포인트가 표시되기를 원한다고 가정합니다. 지도의 확대 / 축소 수준을 16 으로 초기화하여이 작업을 수행했습니다 (V3에서 가장 높은 확대 / 축소 수준인지 확실하지 않음).

var map = new google.maps.Map(document.getElementById('map_canvas'), {
  zoom: 16,
  center: marker_point,
  mapTypeId: google.maps.MapTypeId.ROADMAP
});

그런 다음 나는 범위를 벗어났습니다.

var bounds = new google.maps.LatLngBounds();

// You can have a loop here of all you marker points
// Begin loop
bounds.extend(marker_point);
// End loop

map.fitBounds(bounds);

결과 : 성공!


3

나는 사용한다:

gmap.setZoom(24); //this looks a high enough zoom value
gmap.fitBounds(bounds); //now the fitBounds should make the zoom value only less

코드에 따라 24보다 작고 필요한 확대 / 축소 수준을 사용하지만 어쨌든 확대 / 축소가 변경되어 축소 한 정도에 신경 쓰지 않을 것입니다.


나는 이것을 말하기 싫어하지만이 답변처럼 이상한 것은 지금까지 효과가 있었고 3 일 동안 4-5 시간을 검색했습니다. 그래도 더 나은 솔루션을 찾고 있습니다.
Allov

3

이것을 시도하십시오 :

map.fitBounds(bounds);

// CHANGE ZOOM LEVEL AFTER FITBOUNDS
zoomChangeBoundsListener = google.maps.event.addListenerOnce(map, 'bounds_changed', function(event) {
  if (this.getZoom()){
    this.setZoom(15);
  }
});
setTimeout(function(){
  google.maps.event.removeListener(zoomChangeBoundsListener)
}, 2000);

2

나는 같은 문제가 있었고 다음 코드를 사용하여 해결할 수있었습니다. 이 리스너 ( google.maps.addListenerOnce()) 이벤트 map.fitBounds()는 실행 된 직후에 한 번만 발생 합니다. 따라서 필요가 없습니다

  1. 청취자를 추적하고 수동으로 제거하거나
  2. 지도가가 될 때까지 기다리십시오 idle.

초기에 적절한 확대 / 축소 수준을 설정하고 이벤트 리스너가 만료되었으므로 사용자가 초기 확대 / 축소 수준을지나 확대 / 축소 할 수 있습니다. 예를 들어, google.maps.addListener()호출 만 한 경우 사용자는 지정된 확대 / 축소 수준 (이 경우 4)을 지나서 확대 할 수 없습니다 . 우리가 구현 한 이후로 google.maps.addListenerOnce()사용자는 자신이 선택한 어떤 수준으로도 확대 할 수 있습니다.

map.fitBounds(bounds);

var zoom_level_for_one_marker = 4;

google.maps.event.addListenerOnce(map, 'bounds_changed', function(event){
   if (this.getZoom() >= zoom_level_for_one_marker){  
       this.setZoom(zoom_level_for_one_marker) 
   }
});

2

같은 문제가 있었는데,지도에 많은 마커를 맞추는 데 필요했습니다. 이것은 내 경우를 해결했다.

  1. 한계 선언
  2. koderoid에서 제공하는 사용 체계 (각 마커 세트에 대해 bounds.extend(objLatLng))
  3. 맵이 완료된 후 fitbounds 실행 :

    google.maps.event.addListenerOnce(map, 'idle', function() { 
        map.fitBounds( bounds );
    });

2

전화하기 전에 확인을 수행하여 fitBounds확대하지 않고 갑자기 축소 하는 솔루션을 찾았 습니다.

var bounds = new google.maps.LatLngBounds();

// extend bounds with each point

var minLatSpan = 0.001;
if (bounds.toSpan().lat() > minLatSpan) {
    gmap.fitBounds(bounds); 
} else {
    gmap.setCenter(bounds.getCenter());
    gmap.setZoom(16);
}

원하는 위치에 도달하려면 minLatSpan 변수를 약간 사용해야합니다. 확대 / 축소 수준과 맵 캔버스의 크기에 따라 다릅니다.

위도 대신 경도를 사용할 수도 있습니다


저에게는 효과적이지만 minLatSpan을 사용하지 않습니다.지도에 1 개의 마커가있는 경우에만 확대 / 축소를 설정해야합니다. 따라서 마커가 하나 이상 있는지 확인하고 있습니다.
Micer

2

나는 많은 잘못되었거나 너무 복잡한 솔루션을 보았으므로 작동하는 우아한 솔루션 을 게시하기로 결정했습니다 .

setZoom()예상대로 작동하지 않는 이유 fitBounds()는 비동기식이므로 확대 / 축소를 즉시 업데이트한다는 보장은 없지만 그에 대한 호출 setZoom()은 그에 의존합니다.

고려해야 할 사항은 minZoom전화하기 전에지도 옵션을 설정 fitBounds()한 다음 완료된 후 지워야합니다 (원하는 경우 사용자가 여전히 수동으로 축소 할 수 있음).

var bounds = new google.maps.LatLngBounds();
// ... (extend bounds with all points you want to fit)

// Ensure the map does not get too zoomed out when fitting the bounds.
gmap.setOptions({minZoom: 6});
// Clear the minZoom only after the map fits the bounds (note that
// fitBounds() is asynchronous). The 'idle' event fires when the map
// becomes idle after panning or zooming.
google.maps.event.addListenerOnce(gmap, 'idle', function() {
  gmap.setOptions({minZoom: null});
});

gmap.fitBounds(bounds);

또한 최대 확대 / 축소도 제한하려는 경우 maxZoom속성에 동일한 트릭을 적용 할 수 있습니다 .

MapOptions docs를 참조하십시오 .


1

이 기능을 사용하여 위성 이미지를 사용할 수 있도록 확대 / 축소 수준이 설정 수준을 초과하지 않도록합니다.

zoom_changed이벤트에 리스너를 추가하십시오 . 이는 UI에서 확대 / 축소 컨트롤을 제어 할 수 있다는 추가 이점이 있습니다.

만 실행 setZoom있도록, 필요한 경우 if문에 바람직 Math.max하거나Math.min

   google.maps.event.addListener(map, 'zoom_changed', function() { 
      if ( map.getZoom() > 19 ) { 
        map.setZoom(19); 
      } 
    });
    bounds = new google.maps.LatLngBounds( ... your bounds ... )
    map.fitBounds(bounds);

너무 축소가되지 않도록하려면 :

   google.maps.event.addListener(map, 'zoom_changed', function() { 
      if ( map.getZoom() < 6 ) { 
        map.setZoom(6); 
      } 
    });
    bounds = new google.maps.LatLngBounds( ... your bounds ... )
    map.fitBounds(bounds);

1

이 함수에서는 지오메트리 유형을 저장하기 위해 메타 데이터를 동적으로 추가해야합니다.

"fitGeometries"는 맵 오브젝트를 확장하는 JSON 함수입니다.

"형상"은 MVCArray ()가 아닌 일반적인 자바 스크립트 배열입니다.

geometry.metadata = { type: "point" };
var geometries = [geometry];

fitGeometries: function (geometries) {
    // go and determine the latLngBounds...
    var bounds = new google.maps.LatLngBounds();
    for (var i = 0; i < geometries.length; i++) {
        var geometry = geometries[i];
        switch (geometry.metadata.type)
        {
            case "point":
                var point = geometry.getPosition();
                bounds.extend(point);
                break;
            case "polyline":
            case "polygon": // Will only get first path
                var path = geometry.getPath();
                for (var j = 0; j < path.getLength(); j++) {
                    var point = path.getAt(j);
                    bounds.extend(point);
                }
                break;
        }
    }
    this.getMap().fitBounds(bounds);
},

또는 LatLngBounds 객체에 extend () 메서드가 있다는 것을 모른 채 모든 작업을 수행했습니다. 이것은 훨씬 쉬울 것입니다.
CrazyEnigma

1

이 작업은 API v3에서 고정 줌 설정으로 나에게 적합합니다.

var bounds = new google.maps.LatLngBounds();
// extend bounds with each point

gmap.setCenter(bounds.getCenter()); 
gmap.setZoom( 6 );

1

나처럼, 리스너와 함께 기꺼이 연주하지 않는다면, 이것은 내가 생각해 낸 간단한 해결책입니다.

    map.fitLmtdBounds = function(bounds, min, max){
        if(bounds.isEmpty()) return;
        if(typeof min == "undefined") min = 5;
        if(typeof max == "undefined") max = 15;

        var tMin = this.minZoom, tMax = this.maxZoom;
        this.setOptions({minZoom:min, maxZoom:max});
        this.fitBounds(bounds);
        this.setOptions({minZoom:tMin, maxZoom:tMax});
    }

그런 다음 정의 된 줌 범위에서 범위를 설정하거나 줌 범위 를 재정의하는 map.fitLmtdBounds(bounds)대신 호출 할 수 있습니다 .map.fitBounds(bounds)map.fitLmtdBounds(bounds,3,5)


0

이것을 시도하십시오.

// Find out what the map's zoom level is
zoom = map.getZoom();
if (zoom == 1) {
  // If the zoom level is that low, means it's looking around the
world.
  // Swap the sw and ne coords
  viewportBounds = new
google.maps.LatLngBounds(results[0].geometry.location, initialLatLng);
  map.fitBounds(viewportBounds);
}

이것이 도움이된다면.

모두 제일 좋다


0

경계를 계산 한 후 왼쪽 위와 아래 오른쪽 모서리 사이의 거리를 확인할 수 있습니다. 그런 다음 거리를 테스트하여 확대 / 축소 수준을 이해할 수 있습니다 (거리가 너무 멀면 확대 / 축소 수준이 낮을 수 있음). setbound method 또는 setZoom을 사용하여 wheter를 선택할 수 있습니다.


0

나는 그것을 제안하고 싶지 않지만 시도 해야 한다면 -첫 번째 전화

gmap.fitBounds(bounds);

그런 다음 새 Thread / AsyncTask를 만들고 20-50ms 정도 절전 모드로 전환 한 다음

gmap.setZoom( Math.max(6, gmap.getZoom()) );

UI 스레드에서 ( onPostExecuteAsyncTask에 핸들러 또는 메소드 사용 )

나는 그것이 작동하는지 모른다, 단지 제안. 당신이 당신의 포인트에서 줌 레벨을 어떻게 든 계산하고, 너무 낮지 않은지 확인하고, 수정 한 다음 전화해야합니다.gmap.setZoom(correctedZoom)


0

'bounds_changed'가 올바르게 실행되지 않으면 (때로는 Google에서 좌표를 완벽하게 받아들이지 않는 것 같음) 대신 'center_changed'를 사용해보십시오.

fitBounds ()가 호출 될 때마다 'center_changed'이벤트가 발생하지만, 맵이 이동 한 후 즉시 실행되는 것은 아니지만 반드시 실행됩니다.

일반적인 경우, '유휴'는 여전히 최고의 이벤트 리스너이지만, 일부 사람들이 fitBounds () 호출에서 이상한 문제를 겪을 수 있습니다.

참조 구글은 fitBounds 콜백을 매핑


0

다른 솔루션과 함께 들으려면- "bounds_changed 이벤트를 듣고 새 확대 / 축소를 설정하십시오"접근 방식이 안정적으로 작동하지 않는다는 것을 알았습니다. fitBounds맵이 완전히 초기화되기 전에 전화 를 걸었고 fitBounds경계 및 줌 레벨을 변경 하기 전에 초기화로 인해 리스너를 사용하는 bounds_changed 이벤트가 발생했다고 생각 합니다. 나는이 코드로 끝났는데, 지금까지 작동하는 것 같습니다.

// If there's only one marker, or if the markers are all super close together,
// `fitBounds` can zoom in too far. We want to limit the maximum zoom it can
// use.
//
// `fitBounds` is asynchronous, so we need to wait until the bounds have
// changed before we know what the new zoom is, using an event handler.
//
// Sometimes this handler gets triggered by a different event, before
// `fitBounds` takes effect; that particularly seems to happen if the map
// hasn't been fully initialized yet. So we don't immediately remove the
// listener; instead, we wait until the 'idle' event, and remove it then.
//
// But 'idle' might happen before 'bounds_changed', so we can't set up the
// removal handler immediately. Set it up in the first event handler.

var removeListener = null;
var listener = google.maps.event.addListener(map, 'bounds_changed', () => {
  console.log(map.getZoom());
  if (map.getZoom() > 15) {
    map.setZoom(15);
  }

  if (!removeListener) {
    removeListener = google.maps.event.addListenerOnce(map, 'idle', () => {
      console.log('remove');
      google.maps.event.removeListener(listener);
    });
  }
});

0

나에게 가장 쉬운 해결책은 다음과 같습니다.

map.fitBounds(bounds);

function set_zoom() {
    if(map.getZoom()) {map.setZoom(map.getZoom() - 1);}
    else {setTimeout(set_zoom, 5);}
}
setTimeout(set_zoom, 5);

-1
google.maps.event.addListener(marker, 'dblclick', function () {
    var oldZoom = map.getZoom(); 
    map.setCenter(this.getPosition());
    map.setZoom(parseInt(oldZoom) + 1);
});

-3

내가 한 것은 :

map.setCenter(bounds.getCenter(), map.getBoundsZoomLevel(bounds));

그리고 V3 API에서 작동합니다.


map.setCenter 위도와 경도, 하나의 속성을 받아들이고,지도 getBoundsZoomLevel 같은 아무 기능이없는
빅토르

이 게시물을 본 후 getBoundsZoomLevel과 같은 기능이 있다고 생각했는데 그것이 없다는 것을 알고 실망했습니다.
sedran

내가 getBoundsZoomLevel ()가 Google지도 V2 API의하지 V3 API를 사용할 생각
쿠시
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.