Google Maps v3 fitBounds () Zoom terlalu dekat untuk penanda tunggal


93

Apakah ada cara untuk menyetel tingkat zoom maksimal fitBounds()? Masalah saya adalah ketika peta hanya diumpankan ke satu lokasi, ia memperbesar sejauh mungkin, yang benar-benar mengeluarkan peta dari konteks dan membuatnya tidak berguna. Mungkin saya mengambil pendekatan yang salah?

Terima kasih sebelumnya!


2
stackoverflow.com/questions/4523023/… adalah solusi yang jauh lebih baik. Khusus jawaban @Nequins
Kennet

Jawaban:


139

Saya suka solusi mrt (terutama ketika Anda tidak tahu berapa banyak titik yang akan Anda petakan atau sesuaikan), kecuali itu membuang penanda sehingga tidak lagi berada di tengah peta. Saya hanya memperpanjangnya dengan titik tambahan dengan mengurangi 0,01 dari lat dan lng juga, sehingga penanda tetap berada di tengah. Bekerja dengan baik, terima kasih 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
Ide bagus untuk mempertahankan pusat aslinya. Alasan tingkat zoom tidak dapat disesuaikan secara andal saat menggunakan fitBounds()metode ini karena zoom terjadi secara tidak bersamaan: stackoverflow.com/questions/2989858/…
Metro Smurf

1
Ini bekerja dengan baik untuk saya. Saya memang harus meneruskan referensi peta ke dalam fungsi "function fitToMarkers (markers, map)" di V3, tetapi berfungsi seperti pesona setelah itu!
Shane

4
Suka itu. Bagus @ryan. Berfungsi bagus untuk saya, tetapi 0,01 dalam kasus saya memperkecil terlalu jauh, 0,001 tepat sasaran.
willdanceforfun

Terima kasih. Seperti @willdanceforfun kasus yang sama, 001 tepat sasaran.
Goran Jakovljevic

1
Saya akan merekomendasikan solusi ini stackoverflow.com/questions/2437683/…
NinjaOnSafari

40

Anda dapat mengatur peta Anda dengan maxZoomdi MapOptions (api-reference) seperti ini:

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

Ini akan mencegah peta diperbesar lebih dalam saat menggunakan fitBounds()dan bahkan menghilangkan tingkat zoom dari kontrol zoom.


@ Candlejack Jadi persis seperti yang dijelaskan dalam jawaban saya?
Flygenring

8
Anda dapat menyetel maxZoomsebelum memasang batas dan kemudian membatalkannya lagi menggunakan map.setOptions({ maxZoom: undefined })saat idlediaktifkan dengan mengubah batas. Hal ini mencegah efek zoom in, zoom out alih-alih mengatur ulang zoom di idleacara tersebut.
El Yobo

29

Solusi lain adalah memperluas batas jika Anda mendeteksi itu terlalu kecil sebelum Anda menjalankan 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 });

Menggunakan opsi MaxZoom bekerja paling baik untuk tidak memperbesar untuk mendekati tanda yang Anda miliki.


Fantastis! Penolong!
Jaypee

18

Setelah Anda menambahkan semua batas nyata, tambahkan garis-garis ini

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));

itu mendapatkan pusat batas nyata kemudian menambahkan dua titik tambahan satu ke timur laut dan satu di barat daya pusat Anda

Ini secara efektif mengatur zoom minimum, mengubah nilai offset untuk menambah atau mengurangi zoom


12

Jika ini untuk satu lokasi, Anda dapat menggunakan setCenter () dan setZoom () sebagai gantinya.


solusi termudah
Alberto M

11

kamu bisa menggunakan

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

dengan cara ini Anda mengatur properti peta setelah peta diinisialisasi .... Anda dapat mengaturnya sebanyak yang Anda inginkan ... tetapi dalam kasus Anda ... Anda dapat mengaturnya sebelum fitBounds ()

semoga berhasil, rarutu


7

Cara saya mencegah peta diperbesar jauh adalah dengan menambahkan baris kode ini:

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

Tepat setelah baris ini:

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

Jangan ragu untuk mengubah tingkat zoom ke tingkat apa pun yang Anda tidak ingin peta diperbesar.

Jika Anda memiliki masalah atau pertanyaan, tinggalkan komentar di posting blog yang saya tulis tentang ini di http://icode4you.net/creating-your-own-store-locator-map-how-to-prevent-the- map-from-zooming-in-too close-on-a-single-marker


1
Saya suka solusi ini tetapi masukkan setzoom di dalam if to not call it every time. Mungkin juga ada efek samping waktu yang mengembalikan 'tidak ditentukan' dari getzoom (). Solusi: zoom = map.getZoom (); if (typeof zoom! == 'undefined' && zoom> 8) map.setZoom (8);
Le Droid

5

Saya sangat menyukai solusi mrt dan bekerja dengan sempurna jika Anda selalu hanya memiliki satu poin untuk dikerjakan. Namun saya menemukan bahwa jika kotak pembatas tidak didasarkan pada satu titik, tetapi titik-titik tersebut sangat berdekatan, ini masih dapat menyebabkan peta diperbesar terlalu jauh.

Berikut adalah cara untuk terlebih dahulu memeriksa apakah titik-titik tersebut berada dalam jarak yang ditentukan satu sama lain, kemudian jika mereka lebih kecil dari jarak minimum tersebut, perpanjang batas dengan jarak minimum tersebut:

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);
}

Semoga ini bisa membantu seseorang!


3

Ini memberi Anda kontrol langsung atas zoom maksimum yang diizinkan pada pemasangan batas.

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

Sedangkan untuk saya guys, saya menyelesaikannya dengan membuat acara idle setelah fitBounds. Bekerja dengan sempurna. Tebak itu salah satu solusi paling bersih di sini

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

Saya memecahkan masalah ini, karena Google Maps V3 didorong oleh peristiwa:

Anda dapat memberi tahu API untuk menyetel kembali zoom ke jumlah yang tepat saat peristiwa zoom_changed dipicu :

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

Saya menggunakan awal membuat peta tidak terlalu banyak memperbesar pemuatan ketika akhirnya fitBounds permorfed, tanpanya acara zoom lebih dari 11 tidak akan mungkin bagi pengguna.


1

Setelah fitBounds()metode panggilan , coba atur tingkat zoom lagi. Ini akan memaksa peta berada pada tingkat zoom sementara dipusatkan di tempat yang tepat.


0

Saya memiliki Soulution berdasarkan membatasi zoom maksimal saat menyesuaikan batas. Berfungsi untuk saya (diuji pada 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

Dan .. ini satu lagi.
Ide yang sama seperti mrt dan Ryan, tapi

  • juga berfungsi jika ukuran batas tidak tepat nol (*)
  • mencegah distorsi di dekat kutub
  • menggunakan getCenter () bukan getNorthEast ()

(*) Catatan: Jika kotaknya sudah cukup besar, maka menambahkan dua titik ekstra tersebut seharusnya tidak berpengaruh. Jadi kami tidak perlu pemeriksaan lebih lanjut.

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;
}

EDIT: Saya tidak yakin apakah perhitungan rasio saya benar, mengingat kami memiliki proyeksi Mercator. Saya mungkin mengedit ulang ini ..



-1

Inilah solusi saya, yang juga berfungsi ketika dua penanda sangat dekat. Tingkat zoom maksimum yang efektif sama dalam kedua situasi. Jadi, kami tidak akan melakukan zoom out yang tidak perlu, saat ada lebih dari satu penanda

Efeknya, sekali lagi memastikan zoom maksimum, tanpa menggunakan opsi maxZoom, yang mungkin memiliki efek yang tidak diinginkan sehingga tidak mungkin bagi pengguna untuk melakukan zoom lebih jauh dari level maxZoom dengan kontrol zoom

Saya telah menghitung maxLat, minLat, maxLng dan minLng sebelumnya ...

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,
});
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.