Google Maps v3 - membatasi area yang dapat dilihat dan tingkat zoom

97

apakah mungkin membatasi peta Google v3 ke area tertentu? Saya ingin mengizinkan menampilkan hanya beberapa area (misalnya negara) dan melarang pengguna untuk meluncur ke tempat lain. Saya juga ingin membatasi level zoom - misalnya hanya antara level 6 dan 9. Dan saya ingin menggunakan semua tipe peta dasar.

Apakah ada cara untuk mencapai hal ini?

Saya berhasil sebagian dengan membatasi tingkat zoom dengan menggunakan StyledMap, tetapi saya hanya berhasil membatasi ROADMAP, saya tidak dapat membatasi zoom pada jenis dasar lainnya dengan cara ini.

Terima kasih atas bantuannya

Tomik
sumber

Jawaban:

119

Anda dapat mendengarkan dragendacara tersebut, dan jika peta ditarik ke luar batas yang diizinkan, pindahkan kembali ke dalam. Anda dapat menentukan batas yang diizinkan dalam sebuah LatLngBoundsobjek dan kemudian menggunakan contains()metode ini untuk memeriksa apakah pusat lintang / bujur yang baru berada dalam batas tersebut.

Anda juga dapat membatasi level zoom dengan sangat mudah.

Perhatikan contoh berikut: Fiddle Demo

<!DOCTYPE html>
<html> 
<head> 
   <meta http-equiv="content-type" content="text/html; charset=UTF-8"/> 
   <title>Google Maps JavaScript API v3 Example: Limit Panning and Zoom</title> 
   <script type="text/javascript" 
           src="http://maps.google.com/maps/api/js?sensor=false"></script>
</head> 
<body> 
   <div id="map" style="width: 400px; height: 300px;"></div> 

   <script type="text/javascript"> 

   // This is the minimum zoom level that we'll allow
   var minZoomLevel = 5;

   var map = new google.maps.Map(document.getElementById('map'), {
      zoom: minZoomLevel,
      center: new google.maps.LatLng(38.50, -90.50),
      mapTypeId: google.maps.MapTypeId.ROADMAP
   });

   // Bounds for North America
   var strictBounds = new google.maps.LatLngBounds(
     new google.maps.LatLng(28.70, -127.50), 
     new google.maps.LatLng(48.85, -55.90)
   );

   // Listen for the dragend event
   google.maps.event.addListener(map, 'dragend', function() {
     if (strictBounds.contains(map.getCenter())) return;

     // We're out of bounds - Move the map back within the bounds

     var c = map.getCenter(),
         x = c.lng(),
         y = c.lat(),
         maxX = strictBounds.getNorthEast().lng(),
         maxY = strictBounds.getNorthEast().lat(),
         minX = strictBounds.getSouthWest().lng(),
         minY = strictBounds.getSouthWest().lat();

     if (x < minX) x = minX;
     if (x > maxX) x = maxX;
     if (y < minY) y = minY;
     if (y > maxY) y = maxY;

     map.setCenter(new google.maps.LatLng(y, x));
   });

   // Limit the zoom level
   google.maps.event.addListener(map, 'zoom_changed', function() {
     if (map.getZoom() < minZoomLevel) map.setZoom(minZoomLevel);
   });

   </script> 
</body> 
</html>

Tangkapan layar dari contoh di atas. Pengguna tidak akan dapat menyeret lebih jauh ke selatan atau timur jauh dalam kasus ini:

Google Maps JavaScript API v3 Contoh: Paksa berhenti menyeret peta

Daniel Vassallo
sumber
2
Keputusannya tidak terlihat bersih. Mengapa if (x < minX) x = minX;dan if (x > maxX) x = maxX;tidak mengecualikan satu sama lain? Mengapa Anda memusatkan kanvas pada koordinat minX / maxX dan maxX / maxY meskipun keduanya bukan koordinat pusat?
Alexander Palamarchuk
1
Alih-alih dragendacara yang dapat Anda gunakan draggable: falsepada contoh peta ( contoh yang berfungsi )
machineaddict
Ini bukan teknik yang baik untuk menggunakan peristiwa "zoom_changed" untuk membatasi pengguna. Karena pertama kali itu akan selalu melampaui level min dan kemudian menggunakan kode Anda, Anda menyetel min zoom lagi yang akan membidik layar.
Jitendra Pancholi
periksa zillow.com/homes/for_sale/days_sort/… Mereka telah melakukannya dengan cara yang benar, tidak yakin caranya.
Jitendra Pancholi
1
Ini bekerja dengan sempurna untuk saya jika saya beralih ke center_changedacara, bukan dragend.
Johan B
182

Cara yang lebih baik untuk membatasi tingkat zoom mungkin menggunakan minZoom/ maxZoomoptions daripada bereaksi terhadap kejadian?

var opt = { minZoom: 6, maxZoom: 9 };
map.setOptions(opt);

Atau opsi dapat ditentukan selama inisialisasi peta, misalnya:

var map = new google.maps.Map(document.getElementById('map-canvas'), opt);

Lihat: Referensi Google Maps JavaScript API V3

ChrisV
sumber
3
Nah, ini pasti cara terbaik untuk membatasi level zoom. Saat saya menulis postingan, fitur tersebut tidak ada di Maps API v3. Untungnya, mereka terus meningkatkan API.
Tomik
2
Ini berfungsi dengan sempurna, ini harus menjadi jawaban terbaik untuk zoom.
paullb
3
Ini harus ditandai sebagai jawaban bagi mereka yang melihat hanya pada jawaban yang dipilih.
ErJab
9
pengaturan tingkat zoom tidak berpengaruh pada panning.
simpatico
1
Pasti cara terbaik untuk pergi
ChrisRich
16

Kabar baik. Mulai dari Maps JavaScript API versi 3.35 yang diluncurkan pada 14 Februari 2019, Anda dapat menggunakan restrictionopsi baru untuk membatasi viewport peta.

Menurut dokumentasi

Antarmuka MapRestriction

Batasan yang dapat diterapkan ke Peta. Area pandang peta tidak akan melebihi batasan ini.

sumber: https://developers.google.com/maps/documentation/javascript/reference/map#MapRestriction

Jadi, sekarang Anda hanya menambahkan opsi pembatasan selama inisialisasi peta dan itu. Lihat contoh berikut yang membatasi area pandang ke Swiss

var map;
function initMap() {
  map = new google.maps.Map(document.getElementById('map'), {
    center: {lat: 46.818188, lng: 8.227512},
    minZoom: 7,
    maxZoom: 14,
    zoom: 7,
    restriction: {
      latLngBounds: {
        east: 10.49234,
        north: 47.808455,
        south: 45.81792,
        west: 5.95608
      },
      strictBounds: true
    },
  });
}
#map {
  height: 100%;
}
html, body {
  height: 100%;
  margin: 0;
  padding: 0;
}
<div id="map"></div>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDztlrk_3CnzGHo7CFvLFqE_2bUKEq1JEU&callback=initMap" async defer></script>

Saya harap ini membantu!

xomena
sumber
1
Tautan dokumentasi tetap.
xomena
Terima kasih, kode ini berhasil. Artinya, jika Anda membatasi zoom hingga hanya 1 level yang dimungkinkan dengan minZoom dan maxZoom. Tampaknya Anda perlu mengatur selatan, barat, bukan, timur yang berbeda untuk setiap tingkat zoom jika ini berfungsi sebagaimana mestinya. Akan menyenangkan jika memiliki pengaturan batasan yang berbeda untuk setiap tingkat zoom. Saya menggunakan level zoom out maksimal dan menentukan koordinat dari sana, sehingga memungkinkan untuk keluar dari batas jika Anda memperbesar dan kemudian menggeser.
Kim Steinhaug
6

Untuk membatasi zoom pada v.3 +. dalam pengaturan peta Anda, tambahkan tingkat zoom default dan minZoom atau maxZoom (atau keduanya jika diperlukan) tingkat zoom adalah 0 hingga 19. Anda harus menyatakan tingkat zoom yang tuli jika batasan diperlukan. semua case sensitive!

function initialize() {
   var mapOptions = {
      maxZoom:17,
      minZoom:15,
      zoom:15,
      ....
PERAK DALAM
sumber
3

Cara yang jauh lebih baik untuk membatasi jangkauan ... menggunakan logika berisi dari poster di atas.

var dragStartCenter;

google.maps.event.addListener(map, 'dragstart', function(){
                                       dragStartCenter = map.getCenter();
                                         });

google.maps.event.addListener(this.googleMap, 'dragend', function(){
                            if (mapBounds.contains(map.getCenter())) return;
                    map.setCenter(this.dragStart);
                           });
Menepuk
sumber
Mengapa Anda menambahkan, this.googleMapbukan mapuntuk pendengar kedua? Juga tidak dragStartboleh dragStartCenter? Terakhir apa mapBounds?
Hobbes3
2
Tentunya yang dilakukan hanyalah menghentikan pengguna menyeret jauh dalam satu gerakan seret? Mereka masih bisa membuat banyak hambatan kecil dan berakhir di mana saja, bukan?
Yakobus
1

Ini dapat digunakan untuk memusatkan kembali peta ke lokasi tertentu. Itulah yang saya butuhkan.

    var MapBounds = new google.maps.LatLngBounds(
    new google.maps.LatLng(35.676263, 13.949096),
    new google.maps.LatLng(36.204391, 14.89038));

    google.maps.event.addListener(GoogleMap, 'dragend', function ()
    {
        if (MapBounds.contains(GoogleMap.getCenter()))
        {
            return;
        }
        else
        {
            GoogleMap.setCenter(new google.maps.LatLng(35.920242, 14.428825));
        }
    });
Jonathan Busuttil
sumber
1
myOptions = {
        center: myLatlng,
        minZoom: 6,
        maxZoom: 9,
        styles: customStyles,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
Anup
sumber
1
Ini tidak menjawab pertanyaan itu.
Kit Sunde
0

Inilah varian saya untuk memecahkan masalah batasan area yang dapat dilihat.

        google.maps.event.addListener(this.map, 'idle', function() {
            var minLat = strictBounds.getSouthWest().lat();
            var minLon = strictBounds.getSouthWest().lng();
            var maxLat = strictBounds.getNorthEast().lat();
            var maxLon = strictBounds.getNorthEast().lng();
            var cBounds  = self.map.getBounds();
            var cMinLat = cBounds.getSouthWest().lat();
            var cMinLon = cBounds.getSouthWest().lng();
            var cMaxLat = cBounds.getNorthEast().lat();
            var cMaxLon = cBounds.getNorthEast().lng();
            var centerLat = self.map.getCenter().lat();
            var centerLon = self.map.getCenter().lng();

            if((cMaxLat - cMinLat > maxLat - minLat) || (cMaxLon - cMinLon > maxLon - minLon))
            {   //We can't position the canvas to strict borders with a current zoom level
                self.map.setZoomLevel(self.map.getZoomLevel()+1);
                return;
            }
            if(cMinLat < minLat)
                var newCenterLat = minLat + ((cMaxLat-cMinLat) / 2);
            else if(cMaxLat > maxLat)
                var newCenterLat = maxLat - ((cMaxLat-cMinLat) / 2);
            else
                var newCenterLat = centerLat;
            if(cMinLon < minLon)
                var newCenterLon = minLon + ((cMaxLon-cMinLon) / 2);
            else if(cMaxLon > maxLon)
                var newCenterLon = maxLon - ((cMaxLon-cMinLon) / 2);
            else
                var newCenterLon = centerLon;

            if(newCenterLat != centerLat || newCenterLon != centerLon)
                self.map.setCenter(new google.maps.LatLng(newCenterLat, newCenterLon));
        });

strictBoundsadalah objek new google.maps.LatLngBounds()bertipe. self.gmapmenyimpan objek Google Map ( new google.maps.Map()).

Ini benar-benar berfungsi tetapi jangan hanya lupa untuk memperhitungkan wasir dengan melintasi garis meridian ke 0 dan paralel jika batas Anda menutupinya.

Alexander Palamarchuk
sumber
Algoritme Daniel Vassallo yang diterima tidak berfungsi dengan baik untuk saya. Ada beberapa perbedaan mendasar di sini.
Alexander Palamarchuk
0

Untuk beberapa alasan

if (strictBounds.contains(map.getCenter())) return;

tidak berhasil untuk saya (mungkin masalah belahan bumi selatan). Saya harus mengubahnya menjadi:

    function checkBounds() {
        var c = map.getCenter(),
            x = c.lng(),
            y = c.lat(),
            maxX = strictBounds.getNorthEast().lng(),
            maxY = strictBounds.getNorthEast().lat(),
            minX = strictBounds.getSouthWest().lng(),
            minY = strictBounds.getSouthWest().lat();

        if(x < minX || x > maxX || y < minY || y > maxY) {
            if (x < minX) x = minX;
            if (x > maxX) x = maxX;
            if (y < minY) y = minY;
            if (y > maxY) y = maxY;
            map.setCenter(new google.maps.LatLng(y, x));
        }
    }

Semoga bisa membantu seseorang.

Mayko
sumber
0

Salah satu solusinya adalah seperti, Jika Anda mengetahui garis lintang / lng spesifik.

google.maps.event.addListener(map, 'idle', function() {

    map.setCenter(new google.maps.LatLng(latitude, longitude));
    map.setZoom(8);

});

Jika tidak memiliki lintang / bujur tertentu

google.maps.event.addListener(map, 'idle', function() {

    map.setCenter(map.getCenter());
    map.setZoom(8);

});

atau

google.maps.event.addListener(map, 'idle', function() {

    var bounds = new google.maps.LatLngBounds();
    map.setCenter(bounds.getCenter());
    map.setZoom(8);

});
Jaison
sumber
0

Hingga pertengahan 2016 , tidak ada cara resmi untuk membatasi area yang dapat dilihat. Sebagian besar solusi ad-hoc untuk membatasi batas memiliki kekurangan, karena mereka tidak membatasi secara tepat agar sesuai dengan tampilan peta, mereka hanya membatasinya jika pusat peta berada di luar batas yang ditentukan. Jika Anda ingin membatasi batas ke gambar overlay seperti saya, ini dapat mengakibatkan perilaku seperti yang diilustrasikan di bawah ini, di mana peta yang mendasari terlihat di bawah hamparan gambar kami:

masukkan deskripsi gambar di sini

Untuk mengatasi masalah ini, saya telah membuat perpustakaan , yang berhasil membatasi batas sehingga Anda tidak dapat keluar dari hamparan.

Namun, seperti solusi lain yang ada, ini memiliki masalah "bergetar". Saat pengguna menggeser peta dengan cukup agresif, setelah mereka melepaskan tombol kiri mouse, peta masih terus menggeser dengan sendirinya, secara bertahap melambat. Saya selalu mengembalikan peta ke batas, tetapi itu menghasilkan semacam getaran. Efek panning ini tidak dapat dihentikan dengan cara apa pun yang disediakan oleh Js API saat ini. Tampaknya hingga Google menambahkan dukungan untuk sesuatu seperti map.stopPanningAnimation (), kami tidak akan dapat menciptakan pengalaman yang mulus.

Contoh menggunakan pustaka yang disebutkan, pengalaman batas ketat paling halus yang bisa saya dapatkan:

function initialise(){
  
  var myOptions = {
     zoom: 5,
     center: new google.maps.LatLng(0,0),
     mapTypeId: google.maps.MapTypeId.ROADMAP,
  };
  var map = new google.maps.Map(document.getElementById('map'), myOptions);
  
  addStrictBoundsImage(map);
}

function addStrictBoundsImage(map){
	var bounds = new google.maps.LatLngBounds(
		new google.maps.LatLng(62.281819, -150.287132),
		new google.maps.LatLng(62.400471, -150.005608));

	var image_src = 'https://developers.google.com/maps/documentation/' +
		'javascript/examples/full/images/talkeetna.png';

	var strict_bounds_image = new StrictBoundsImage(bounds, image_src, map);
}
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
      <script type="text/javascript">
        google.load("maps", "3",{other_params:"sensor=false"});
      </script>
<body style="margin:0px; padding:0px;" onload="initialise()">
	 <div id="map" style="height:400px; width:500px;"></div>
     <script  type="text/javascript"src="https://raw.githubusercontent.com/matej-pavla/StrictBoundsImage/master/StrictBoundsImage.js"></script>
</body>

Perpustakaan juga dapat menghitung batasan zoom minimum secara otomatis. Kemudian membatasi tingkat zoom menggunakan minZoomatribut peta.

Mudah-mudahan ini membantu seseorang yang menginginkan solusi yang sepenuhnya menghormati batasan yang diberikan dan tidak ingin membiarkannya keluar.

Matej P.
sumber
-4

Ini mungkin berguna.

  var myOptions = {
      center: new google.maps.LatLng($lat,$lang),
      zoom: 7,
      disableDefaultUI: true,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    };

Tingkat Zoom dapat disesuaikan sesuai kebutuhan.

Samir Dash
sumber
Ini tidak menjawab pertanyaan awal tentang membatasi tingkat zoom ke suatu rentang e.g. only between levels 6 and 9, ini menetapkan tingkat zoom default dan menghapus UI default (yaitu +/ -) yang sedikit berlebihan.
Alastair