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.