Google Maps v3 fitBounds () Thu phóng quá gần đối với một điểm đánh dấu


92

Có cách nào để đặt mức thu phóng tối đa cho fitBounds()không? Vấn đề của tôi là khi bản đồ chỉ được cung cấp một vị trí, nó sẽ phóng to hết mức có thể, điều này thực sự đưa bản đồ ra khỏi ngữ cảnh và khiến nó trở nên vô dụng. Có lẽ tôi đang tiếp cận sai?

Cảm ơn trước!


2
stackoverflow.com/questions/4523023/… là một giải pháp tốt hơn nhiều. Câu trả lời @Nequins cụ thể
Kennet

Câu trả lời:


138

Tôi thích giải pháp của mrt (đặc biệt là khi bạn không biết mình sẽ lập bản đồ hoặc điều chỉnh bao nhiêu điểm), ngoại trừ việc nó ném điểm đánh dấu để nó không nằm ở trung tâm của bản đồ nữa. Tôi chỉ đơn giản là mở rộng nó bằng một điểm bổ sung trừ đi 0,01 từ vĩ độ và lng, vì vậy nó giữ điểm đánh dấu ở trung tâm. Hoạt động tuyệt vời, cảm ơn mrt!

// Pan & Zoom map to show all markers
function fitToMarkers(markers) {

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

    // Create bounds from markers
    for( var index in markers ) {
        var latlng = markers[index].getPosition();
        bounds.extend(latlng);
    }

    // Don't zoom in too far on only one marker
    if (bounds.getNorthEast().equals(bounds.getSouthWest())) {
       var extendPoint1 = new google.maps.LatLng(bounds.getNorthEast().lat() + 0.01, bounds.getNorthEast().lng() + 0.01);
       var extendPoint2 = new google.maps.LatLng(bounds.getNorthEast().lat() - 0.01, bounds.getNorthEast().lng() - 0.01);
       bounds.extend(extendPoint1);
       bounds.extend(extendPoint2);
    }

    map.fitBounds(bounds);

    // Adjusting zoom here doesn't work :/

}

4
Ý tưởng tốt về việc giữ trung tâm ban đầu. Lý do mức độ phóng không thể điều chỉnh cách đáng tin cậy khi sử dụng fitBounds()phương pháp là do zoom đang diễn ra không đồng bộ: stackoverflow.com/questions/2989858/...
Metro Smurf

1
Nó hiệu quả tuyệt vời đối với tôi. Tôi đã phải chuyển tham chiếu bản đồ vào hàm "function fitToMarkers (điểm đánh dấu, bản đồ)" trên V3, nhưng nó hoạt động như một sự quyến rũ sau đó!
Shane

4
Yêu mà. Tốt lắm @ryan. Rất hiệu quả đối với tôi, nhưng 0,01 trong trường hợp của tôi thu nhỏ quá xa, 0,001 đã đạt điểm tốt.
willdanceforfun

Cảm ơn. Giống như trường hợp tương tự của @willdanceforfun, 001 đã thành công.
Goran Jakovljevic

1
Tôi muốn giới thiệu giải pháp này stackoverflow.com/questions/2437683/…
NinjaOnSafari,

38

Bạn có thể thiết lập bản đồ của bạn với maxZoomtrong MapOptions (api-tài liệu tham khảo) như thế này:

var map = new google.maps.Map(document.getElementById("map"), { maxZoom: 10 });

Điều này sẽ giúp bản đồ không bị phóng to hơn nữa khi sử dụng fitBounds()và thậm chí loại bỏ các mức thu phóng khỏi điều khiển thu phóng.


@candlejack Vì vậy, chính xác như được mô tả trong câu trả lời của tôi?
Flygenring

6
Bạn có thể đặt maxZoomtrước khi lắp các giới hạn và sau đó bỏ đặt lại bằng cách sử dụng map.setOptions({ maxZoom: undefined })trong idlesự kiện được kích hoạt bằng cách thay đổi các giới hạn. Điều này ngăn hiệu ứng phóng to, thu nhỏ thay vì đặt lại thu phóng trong idlesự kiện.
El Yobo

29

Một giải pháp khác là mở rộng giới hạn nếu bạn phát hiện thấy chúng quá nhỏ trước khi bạn thực thi fitBounds ():

var bounds = new google.maps.LatLngBounds();
// here you extend your bound as you like
// ...
if (bounds.getNorthEast().equals(bounds.getSouthWest())) {
   var extendPoint = new google.maps.LatLng(bounds.getNorthEast().lat() + 0.01, bounds.getNorthEast().lng() + 0.01);
   bounds.extend(extendPoint);
}
map.fitBounds(bounds);

19
var map = new google.maps.Map(document.getElementById("map"), { maxZoom: 10 });

Sử dụng tùy chọn MaxZoom hoạt động tốt nhất để không phóng to đến gần các điểm bạn có.


Tuyệt diệu! Tiết kiệm cuộc sống!
Jaypee

18

Khi bạn đã thêm tất cả các giới hạn thực, hãy thêm các dòng này

var offset = 0.002;     
var center = bounds.getCenter();                            
bounds.extend(new google.maps.LatLng(center.lat() + offset, center.lng() + offset));
bounds.extend(new google.maps.LatLng(center.lat() - offset, center.lng() - offset));

nó lấy trung tâm của các giới hạn thực sau đó thêm hai điểm bổ sung, một ở phía đông bắc và một ở phía tây nam của trung tâm bạn

Điều này có hiệu quả đặt thu phóng tối thiểu, thay đổi giá trị của độ lệch để tăng hoặc giảm thu phóng


12

Nếu nó dành cho một vị trí, bạn có thể sử dụng setCenter () và setZoom () để thay thế.


giải pháp đơn giản nhất
Alberto M

11

bạn có thể sử dụng

map.setOptions({
    maxZoom: [what u want],
    minZoom: [what u want]
});

theo cách này bạn đặt các thuộc tính của bản đồ sau khi bản đồ đã được khởi tạo .... bạn có thể đặt chúng bao nhiêu lần tùy thích ... nhưng trong trường hợp của bạn ... bạn có thể đặt chúng trước fitBounds ()

chúc may mắn, rarutu


7

Cách tôi ngăn bản đồ phóng to ra xa là thêm dòng mã sau:

var zoomOverride = map.getZoom();
        if(zoomOverride > 15) {
        zoomOverride = 15;
        }
      map.setZoom(zoomOverride);

Trực tiếp sau dòng này:

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

Hãy thoải mái thay đổi mức thu phóng thành bất kỳ mức nào bạn không muốn bản đồ thu phóng qua.

Nếu bạn có bất kỳ vấn đề hoặc câu hỏi nào, chỉ cần để lại nhận xét cho tôi về bài đăng trên blog mà tôi đã viết về điều này tại http://icode4you.net/creating-your-own-store-locator-map-how-to-prevent-the- map-from-zoom-in-too-close-on-a-single-marker


1
Tôi thích giải pháp này nhưng chèn setzoom bên trong if để không gọi nó mỗi lần. Cũng có thể có một tác dụng phụ về thời gian trả về 'không xác định' từ getzoom (). Giải pháp: zoom = map.getZoom (); if (typeof zoom! == 'undefined' && zoom> 8) map.setZoom (8);
Le Droid

5

Tôi thực sự thích giải pháp của mrt và nó hoạt động hoàn hảo nếu bạn luôn chỉ có một điểm để làm việc. Tuy nhiên, tôi nhận thấy rằng nếu hộp giới hạn không dựa trên một điểm, mà các điểm rất gần nhau, điều này vẫn có thể khiến bản đồ bị phóng to quá xa.

Dưới đây là một cách để kiểm tra trước tiên nếu các điểm nằm trong một khoảng cách xác định của nhau, sau đó nếu chúng nhỏ hơn khoảng cách tối thiểu đó, hãy mở rộng giới hạn bằng khoảng cách tối thiểu đó:

var bounds = new google.maps.LatLngBounds();
// here you extend your bound as you like

// ...

var minDistance = 0.002;
var sumA = bounds.getNorthEast().lng() - bounds.getSouthWest().lng();
var sumB = bounds.getNorthEast().lat() - bounds.getSouthWest().lat();

if((sumA < minDistance && sumA > -minDistance) 
&& (sumB < minDistance && sumB > -minDistance)){
var extendPoint1 = new google.maps.LatLng(bounds.getNorthEast().lat() + minDistance, bounds.getNorthEast().lng() + minDistance);
    var extendPoint2 = new google.maps.LatLng(bounds.getNorthEast().lat() - minDistance, bounds.getNorthEast().lng() - minDistance);
    bounds.extend(extendPoint1);
    bounds.extend(extendPoint2);
}

Hy vọng điều này sẽ giúp ai đó!


3

Điều này cho phép bạn kiểm soát trực tiếp khi thu phóng tối đa được phép trên giới hạn phù hợp.

var fitToMarkers = function(map, markers, maxZoom) {
    if (typeof maxZoom == 'undefined') maxZoom = 15;

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

    var bounds = new google.maps.LatLngBounds();
    for (var m = 0; m < markers.length; m++) {
        var marker = markers[m];
        var latlng = marker.getPosition();
        bounds.extend(latlng);
    }

    map.fitBounds(bounds);
};

3

Đối với tôi, các bạn, tôi giải quyết nó bằng cách tạo một sự kiện nhàn rỗi sau fitBounds. Hoạt động hoàn hảo. Đoán đó là một trong những giải pháp sạch nhất ở đây

var locations = [['loc', lat, lng], ['loc', lat, lng]];
.....
for (i = 0; i < locations.length; i++) { 
  var map = new google.maps.Map(document.getElementById('map'), {
    zoom: 10
  });
  .... create markers, etc.
}
....
map.fitBounds(bounds);  
google.maps.event.addListenerOnce(map, 'idle', function() {
  if (locations.length == 1) {
    map.setZoom(11);
  }
});

2

Tôi đã giải quyết được vấn đề này, vì Google Maps V3 được điều khiển bởi sự kiện:

bạn có thể yêu cầu API đặt lại mức thu phóng ở mức thích hợp khi sự kiện zoom_changed kích hoạt:

var initial = true
google.maps.event.addListener(map, "zoom_changed", function() {
    if (intial == true){
       if (map.getZoom() > 11) {
         map.setZoom(11);
         intial = false;
       }
    }
}); 

Tôi đã sử dụng intial làm cho bản đồ không phóng to quá nhiều khi tải fitBounds cuối cùng, nếu không có nó thì bất kỳ sự kiện thu phóng nào trên 11 sẽ không thể xảy ra đối với người dùng.


1

Sau khi gọi fitBounds()phương thức, hãy thử thiết lập lại mức thu phóng. Nó sẽ buộc bản đồ ở mức thu phóng đó trong khi căn giữa ở đúng vị trí.


0

Tôi đã thận trọng dựa trên việc giới hạn zoom tối đa khi phù hợp với giới hạn. Hoạt động cho tôi (được thử nghiệm trên Win 7 - IE 9, FF 13, Chrome 19):

// When fitting bounds:
var bounds = new google.maps.LatLngBounds();
// ...
// extend bounds as you like
// ..

// now set global variable when fitting bounds
window.fittingBounds = true;
map.fitBounds(bounds);
window.fittingBounds = false;


// attach this event listener after map init
google.maps.event.addListener(map, 'zoom_changed', function() {
    // set max zoom only when fitting bounds
    if (window.fittingBounds && map.getZoom() > 16) {
        this.setZoom(16);
    }
});

0

Và .. đây là một cái khác.
Ý tưởng tương tự như mrt và Ryan, nhưng

  • cũng hoạt động nếu kích thước giới hạn không chính xác bằng 0 (*)
  • ngăn chặn sự biến dạng gần các cực
  • sử dụng getCenter () thay vì getNorthEast ()

(*) Lưu ý: Nếu ô đã đủ lớn thì việc cộng thêm hai điểm đó cũng không ảnh hưởng gì. Vì vậy chúng tôi không cần kiểm tra thêm.

function calcBounds(markers) {
  // bounds that contain all markers
  var bounds = new google.maps.LatLngBounds();
  // Using an underscore _.each(). Feel free to replace with standard for()
  _.each(markers, function(marker) {
    bounds.extend(marker.getPosition());
  });
  // prevent lat/lng distortion at the poles
  var lng0 = bounds.getNorthEast().lng();
  var lng1 = bounds.getSouthWest().lng();
  if (lng0 * lng1 < 0) {
    // Take the cos at the equator.
    var cos = 1;
  }
  else {
    var cos0 = Math.cos(lng0);
    var cos1 = Math.cos(lng1);
    // Prevent division by zero if the marker is exactly at the pole.
    var cos_safe = Math.max(cos0, cos1, 0.0001);
  }
  var cos0 = Math.cos(bounds.getNorthEast.lng() * Math.PI / 180);
  var cos1 = Math.cos(bounds.getSouthWest.lng() * Math.PI / 180);
  // "radius" in either direction.
  // 0.0006 seems to be an ok value for a typical city.
  // Feel free to make this value a function argument.
  var rLat = 0.0006;
  var rLng = rLat / cos_safe;
  // expand the bounds to a minimum width and height
  var center = bounds.getCenter();
  var p0 = new google.maps.LatLng(center.lat() - rLat, center.lng() - rLng);
  var p1 = new google.maps.LatLng(lat.center() + rLat, center.lng() + rLng);
  bounds.extend(p0);
  bounds.extend(p1);
  return bounds;
}

CHỈNH SỬA: Tôi không chắc liệu tính toán tỷ lệ của mình có chính xác hay không, vì chúng tôi có phép chiếu Mercator. Tôi có thể chỉnh sửa lại cái này ..



-1

Đây là giải pháp của tôi, cũng hoạt động khi hai điểm đánh dấu ở rất gần nhau. Mức thu phóng tối đa hiệu quả là như nhau trong cả hai trường hợp. Vì vậy, chúng tôi không kết thúc việc phóng to một cách vô cớ, khi có nhiều hơn một điểm đánh dấu

Hiệu quả, một lần nữa là đảm bảo thu phóng tối đa, mà không sử dụng tùy chọn maxZoom, có thể có tác dụng không mong muốn là khiến người dùng không thể thu phóng xa hơn mức maxZoom bằng điều khiển thu phóng

Tôi đã tính toán trước maxLat, minLat, maxLng và minLng

var minLatSpan = 0.002;
if (maxLat - minLat < minLatSpan) {
  // ensures that we do not zoom in too much
  var delta = (minLatSpan - (maxLat - minLat)) / 2;
  maxLat += delta;
  minLat -= delta;
}

map.fitBounds({
  east: maxLng,
  west: minLng,
  north: maxLat,
  south: minLat,
});
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.