Google Maps v3 - Limitez la zone visible et le niveau de zoom

97

est-il possible de limiter Google map v3 à une certaine zone? Je veux autoriser l'affichage uniquement d'une zone (par exemple un pays) et interdire à l'utilisateur de glisser ailleurs. Je souhaite également limiter le niveau de zoom, par exemple uniquement entre les niveaux 6 et 9. Et je souhaite utiliser tous les types de carte de base.

Y'a-t-il une quelconque façon de réussir cela?

J'ai eu un succès partiel avec la limitation du niveau de zoom en utilisant StyledMap, mais je n'ai réussi qu'en limitant ROADMAP, je n'ai pas pu limiter le zoom sur d'autres types de base de cette façon.

Merci pour toute aide

Tomik
la source

Réponses:

119

Vous pouvez écouter l' dragendévénement et si la carte est déplacée en dehors des limites autorisées, replacez-la à l'intérieur. Vous pouvez définir vos limites autorisées dans un LatLngBoundsobjet, puis utiliser la contains()méthode pour vérifier si le nouveau centre lat / lng se trouve dans les limites.

Vous pouvez également limiter le niveau de zoom très facilement.

Prenons l'exemple suivant: 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>

Capture d'écran de l'exemple ci-dessus. L'utilisateur ne pourra pas traîner plus au sud ou à l'extrême est dans ce cas:

Exemple d'API JavaScript Google Maps v3: Forcer l'arrêt du glissement de la carte

Daniel Vassallo
la source
2
La décision n'a pas l'air claire. Pourquoi if (x < minX) x = minX;et if (x > maxX) x = maxX;ne pas s'exclure? Pourquoi centrez-vous le canevas sur les coordonnées minX / maxX et maxX / maxY alors qu'elles ne sont pas des coordonnées du centre?
Alexander Palamarchuk
1
Au lieu d'un dragendévénement, vous pouvez utiliser draggable: falsesur une instance de carte ( exemple de travail )
machineaddict
Ce n'est pas une bonne technique pour utiliser l'événement "zoom_changed" pour restreindre l'utilisateur. Parce que la première fois, il ira toujours au-delà du niveau minimum, puis en utilisant votre code, vous réglez à nouveau le zoom minimum qui fera flikr l'écran.
Jitendra Pancholi
vérifiez zillow.com/homes/for_sale/days_sort/ ... Ils l'ont fait de manière correcte, je ne sais pas comment.
Jitendra Pancholi
1
Cela fonctionnait parfaitement pour moi si je passais à l' center_changedévénement au lieu de dragend.
Johan B
182

Une meilleure façon de restreindre le niveau de zoom pourrait être d'utiliser les options minZoom/ maxZoomplutôt que de réagir aux événements?

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

Ou les options peuvent être spécifiées lors de l'initialisation de la carte, par exemple:

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

Voir: Référence de l'API JavaScript de Google Maps V3

ChrisV
la source
3
Maintenant, c'est sûrement le meilleur moyen de restreindre le niveau de zoom. Lorsque j'écrivais l'article, la fonctionnalité n'était pas présente dans l'API Maps v3. Heureusement, ils continuent d'améliorer l'API.
Tomik
2
Cela fonctionne parfaitement, cela devrait être la meilleure réponse pour le zoom.
paullb
3
Cela devrait être marqué comme la réponse pour ceux qui ne regardent que la réponse choisie.
ErJab
9
le réglage du niveau de zoom n'a aucun effet sur le panoramique.
simpatico
1
Certainement la meilleure façon d'aller
ChrisRich
16

Bonnes nouvelles. À partir de la version 3.35 de l'API JavaScript Maps, lancée le 14 février 2019, vous pouvez utiliser une nouvelle restrictionoption afin de limiter la fenêtre d'affichage de la carte.

Selon la documentation

Interface MapRestriction

Une restriction qui peut être appliquée à la carte. La fenêtre d'affichage de la carte ne dépassera pas ces restrictions.

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

Donc, maintenant, vous ajoutez simplement une option de restriction lors d'une initialisation de la carte et cela. Jetez un œil à l'exemple suivant qui limite la fenêtre d'affichage à la Suisse

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>

J'espère que ça aide!

xomena
la source
1
Lien de documentation fixe.
xomena
Merci, ce code a fonctionné. Autrement dit, si vous limitez le zoom à un seul niveau possible avec minZoom et maxZoom. Il semble que vous deviez définir différents sud, ouest, rien, est pour chaque niveau de zoom si cela fonctionne comme prévu. Ce serait bien d'avoir un paramètre de restriction différent pour chaque niveau de zoom. Je suis allé pour mon niveau de zoom arrière maximum et j'ai défini les coordonnées à partir de là, ce qui permet de faire un panoramique hors des limites si vous zoomez puis faites un panoramique.
Kim Steinhaug
6

Pour limiter le zoom sur v.3 +. dans les paramètres de votre carte, ajoutez le niveau de zoom par défaut et les niveaux de zoom minZoom ou maxZoom (ou les deux si nécessaire) vont de 0 à 19. Vous devez déclarer un niveau de zoom sourd si une limitation est requise. tous sont sensibles à la casse!

function initialize() {
   var mapOptions = {
      maxZoom:17,
      minZoom:15,
      zoom:15,
      ....
ARGENT PROFOND
la source
3

Une bien meilleure façon de limiter la portée ... utilisé la logique contient de l'affiche ci-dessus.

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);
                           });
Tapoter
la source
Pourquoi ajoutez-vous this.googleMapau lieu de mappour le deuxième auditeur? Ne devrait pas non plus l' dragStartêtre dragStartCenter? Enfin qu'est-ce que c'est mapBounds?
hobbes3
2
Sûrement tout ce que cela fait est d'empêcher l'utilisateur de glisser trop loin en un seul mouvement de traînée? Ils pourraient encore faire beaucoup de petits drags et finir n'importe où, non?
James
1

Cela peut être utilisé pour recentrer la carte vers un emplacement spécifique. C'est ce dont j'avais besoin.

    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
la source
1
myOptions = {
        center: myLatlng,
        minZoom: 6,
        maxZoom: 9,
        styles: customStyles,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    };
Anup
la source
1
Cela ne répond pas à la question.
Kit Sunde
0

Voici ma variante pour résoudre le problème de la limitation de la zone visible.

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

strictBoundsest un objet de new google.maps.LatLngBounds()type. self.gmapstocke un objet Google Map ( new google.maps.Map()).

Cela fonctionne vraiment mais n'oubliez pas seulement de prendre en compte les hémorroïdes avec croisement du 0e méridien et des parallèles si vos limites les couvrent.

Alexander Palamarchuk
la source
Accepté L'algorithme de Daniel Vassallo ne fonctionne pas correctement pour moi. Il y a ici plusieurs différences principales.
Alexander Palamarchuk
0

Pour certaines raisons

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

n'a pas fonctionné pour moi (peut-être un problème d'hémisphère sud). J'ai dû le changer pour:

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

J'espère que cela aidera quelqu'un.

Mayko
la source
0

Une solution est comme, si vous connaissez la lat / lng spécifique.

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

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

});

Si vous n'avez pas de lat / lng spécifique

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

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

});

ou

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

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

});
Jaison
la source
0

À partir du milieu de 2016 , il n'existe aucun moyen officiel de restreindre la zone visible. La plupart des solutions ad hoc pour restreindre les limites ont cependant un défaut, car elles ne limitent pas les limites exactement pour s'adapter à la vue de la carte, elles ne la restreignent que si le centre de la carte est en dehors des limites spécifiées. Si vous souhaitez limiter les limites à une image superposée comme moi, cela peut entraîner un comportement comme illustré ci-dessous, où la carte sous-jacente est visible sous notre superposition d'image:

entrez la description de l'image ici

Pour résoudre ce problème, j'ai créé une bibliothèque qui a réussi à restreindre les limites afin que vous ne puissiez pas sortir de la superposition.

Cependant, comme d'autres solutions existantes, il a un problème «vibrant». Lorsque l'utilisateur effectue un panoramique de la carte de manière suffisamment agressive, après avoir relâché le bouton gauche de la souris, la carte continue à se déplacer d'elle-même, ralentissant progressivement. Je renvoie toujours la carte aux limites, mais cela se traduit par une sorte de vibration. Cet effet de panoramique ne peut pas être arrêté avec les moyens fournis par l'API Js pour le moment. Il semble que jusqu'à ce que Google ajoute la prise en charge de quelque chose comme map.stopPanningAnimation (), nous ne serons pas en mesure de créer une expérience fluide.

Exemple utilisant la bibliothèque mentionnée, l'expérience de limites strictes la plus fluide que j'ai pu obtenir:

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>

La bibliothèque est également capable de calculer automatiquement la restriction de zoom minimum. Il restreint ensuite le niveau de zoom à l'aide de minZooml'attribut de la carte.

Espérons que cela aide quelqu'un qui veut une solution qui respecte pleinement les limites données et ne veut pas permettre de s'en éloigner.

Matej P.
la source
-4

Cela peut être utile.

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

Le niveau de zoom peut être personnalisable en fonction des besoins.

Samir Dash
la source
Cela ne répond pas à la question initiale de restreindre le niveau de zoom à une plage e.g. only between levels 6 and 9, cela définit le niveau de zoom par défaut et supprime l'interface utilisateur par défaut (c'est +-à- dire / -) qui est un peu exagérée.
Alastair