Google Maps v3 - จำกัด พื้นที่ดูและระดับการซูม


98

เป็นไปได้หรือไม่ที่จะ จำกัด Google map v3 ไว้เฉพาะบางพื้นที่ ฉันต้องการอนุญาตให้แสดงเฉพาะบางพื้นที่ (เช่นประเทศ) และไม่อนุญาตให้ผู้ใช้เลื่อนไปที่อื่น นอกจากนี้ฉันต้องการ จำกัด ระดับการซูม - เช่นระหว่างระดับ 6 และ 9 เท่านั้นและฉันต้องการใช้ประเภทแผนที่ฐานทั้งหมด

มีวิธีใดบ้างที่จะบรรลุสิ่งนี้?

ฉันประสบความสำเร็จบางส่วนกับการ จำกัด ระดับการซูมโดยใช้ StyledMap แต่ฉันประสบความสำเร็จด้วยการ จำกัด ROADMAP เท่านั้นฉันไม่สามารถ จำกัด การซูมในประเภทพื้นฐานอื่น ๆ ได้ด้วยวิธีนี้

ขอบคุณสำหรับความช่วยเหลือใด ๆ

คำตอบ:


119

คุณสามารถฟังdragendเหตุการณ์และหากแผนที่ถูกลากออกนอกขอบเขตที่อนุญาตให้ย้ายกลับเข้าไปด้านใน คุณสามารถกำหนดขอบเขตที่อนุญาตของคุณในLatLngBoundsวัตถุจากนั้นใช้contains()วิธีการตรวจสอบว่าศูนย์ lat / lng ใหม่อยู่ภายในขอบเขตหรือไม่

คุณยังสามารถ จำกัด ระดับการซูมได้อย่างง่ายดาย

พิจารณาตัวอย่างต่อไปนี้: 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>

ภาพหน้าจอจากตัวอย่างด้านบน ผู้ใช้จะไม่สามารถลากไปทางทิศใต้หรือตะวันออกไกลออกไปได้ในกรณีนี้:

Google Maps JavaScript API v3 ตัวอย่าง: บังคับหยุดการลากแผนที่


2
การตัดสินใจดูไม่สะอาด ทำไมif (x < minX) x = minX;และif (x > maxX) x = maxX;ไม่กีดกันซึ่งกันและกัน? เหตุใดคุณจึงวางผ้าใบไว้ที่พิกัด minX / maxX และ maxX / maxY ทั้งๆที่มันไม่ใช่พิกัดของศูนย์
Alexander Palamarchuk

1
แทนที่จะเป็นdragendเหตุการณ์ที่คุณสามารถใช้draggable: falseบนอินสแตนซ์แผนที่ ( ตัวอย่างการทำงาน )
machineaddict

นี่ไม่ใช่เทคนิคที่ดีในการใช้เหตุการณ์ "zoom_changed" เพื่อ จำกัด ผู้ใช้ เนื่องจากในครั้งแรกจะเกินกว่าระดับต่ำสุดเสมอจากนั้นใช้รหัสของคุณคุณกำลังตั้งค่าการซูมขั้นต่ำอีกครั้งซึ่งจะทำให้หน้าจอสั่น
Jitendra Pancholi

ตรวจสอบzillow.com/homes/for_sale/days_sort/…พวกเขาทำถูกต้องไม่แน่ใจว่าอย่างไร
Jitendra Pancholi

1
นี้ทำงานได้อย่างสมบูรณ์แบบสำหรับผมถ้าผมเปลี่ยนไปเหตุการณ์แทนcenter_changed dragend
Johan B

182

วิธีที่ดีกว่าในการ จำกัด ระดับการซูมอาจใช้minZoom/ maxZoomตัวเลือกแทนการตอบสนองต่อเหตุการณ์?

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

หรือสามารถระบุตัวเลือกได้ในระหว่างการเริ่มต้นแผนที่เช่น:

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

โปรดดู: ข้อมูลอ้างอิง Google Maps JavaScript API V3


3
ตอนนี้เป็นวิธีที่ดีที่สุดในการ จำกัด ระดับการซูม เมื่อฉันเขียนโพสต์คุณลักษณะนี้ไม่มีอยู่ใน Maps API v3 โชคดีที่พวกเขาปรับปรุง API อยู่เสมอ
Tomik

2
มันทำงานได้ดีนี่น่าจะเป็นคำตอบที่ดีที่สุดสำหรับการซูม
paullb

3
สิ่งนี้ควรถูกทำเครื่องหมายว่าเป็นคำตอบสำหรับผู้ที่มองเฉพาะคำตอบที่เลือก
ErJab

9
การตั้งระดับการซูมไม่มีผลต่อการแพนกล้อง
simpatico

1
วิธีที่ดีที่สุดแน่นอน
ChrisRich

18

ข่าวดี. ตั้งแต่เวอร์ชัน 3.35 ของ Maps JavaScript API ซึ่งเปิดตัวเมื่อวันที่ 14 กุมภาพันธ์ 2019 คุณสามารถใช้ใหม่ได้restrictionตัวเลือกเพื่อ จำกัด วิวพอร์ตของแผนที่ได้

ตามเอกสารประกอบ

อินเทอร์เฟซ MapRestriction

ข้อ จำกัด ที่สามารถใช้ได้กับแผนที่ วิวพอร์ตของแผนที่จะไม่เกินข้อ จำกัด เหล่านี้

แหล่งที่มา: https://developers.google.com/maps/documentation/javascript/reference/map#MapRestriction

ตอนนี้คุณเพียงแค่เพิ่มตัวเลือกข้อ จำกัด ระหว่างการเริ่มต้นแผนที่และมัน ดูตัวอย่างต่อไปนี้ที่ จำกัด วิวพอร์ตไว้ที่สวิตเซอร์แลนด์

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>

ฉันหวังว่านี่จะช่วยได้!


ลิงก์ไม่ทำงาน นี่คือสิ่งใหม่ในหัวข้อนี้: ตัวอย่าง: developers-dot-devsite-v2-prod.appspot.com/maps/documentation/… DOCS: developers-dot-devsite-v2-prod.appspot.com/maps/documentation/ …
อดัม

1
ลิงก์เอกสารคงที่
xomena

ขอบคุณรหัสประเภทนี้ใช้งานได้ นั่นคือถ้าคุณ จำกัด การซูมไว้ที่ 1 ระดับเท่านั้นที่เป็นไปได้ด้วย minZoom และ maxZoom ดูเหมือนว่าคุณต้องตั้งค่าทิศใต้ทิศตะวันตกไม่ใช่ทิศตะวันออกสำหรับระดับการซูมแต่ละระดับจึงจะทำงานได้ตามที่ตั้งใจไว้ จะดีที่จะมีการตั้งค่าข้อ จำกัด ที่แตกต่างกันสำหรับแต่ละระดับการซูม ฉันไปที่ระดับการซูมออกสูงสุดและกำหนดพิกัดจากที่นั่นจึงทำให้สามารถเลื่อนออกจากขอบเขตได้หากคุณซูมเข้าแล้วแพน
Kim Steinhaug

6

เพื่อ จำกัด การซูมที่ v.3 + ในการตั้งค่าแผนที่ของคุณเพิ่มระดับการซูมเริ่มต้นและ minZoom หรือ maxZoom (หรือทั้งสองอย่างหากจำเป็น) ระดับการซูมคือ 0 ถึง 19 คุณต้องประกาศระดับการซูมแบบหูหนวกหากจำเป็นต้องมีข้อ จำกัด ทั้งหมดเป็นกรณีที่ละเอียดอ่อน!

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

3

วิธีที่ดีกว่ามากในการ จำกัด ช่วง ... ใช้ตรรกะมีจากโปสเตอร์ด้านบน

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

ทำไมคุณเพิ่มthis.googleMapแทนที่จะmapเป็นผู้ฟังที่สอง นอกจากนี้ยังไม่ควรdragStartจะเป็นdragStartCenter? สุดท้ายคือmapBoundsอะไร?
hobbes3

2
แน่นอนว่าทั้งหมดที่หยุดผู้ใช้ลากไปไกลในการลากครั้งเดียว? พวกเขายังสามารถลากเส้นเล็ก ๆ น้อย ๆ และจบลงได้ทุกที่ไม่ใช่เหรอ?
James

1

สามารถใช้เพื่อปรับศูนย์กลางของแผนที่ไปยังตำแหน่งที่ต้องการ ซึ่งเป็นสิ่งที่ฉันต้องการ

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


0

นี่คือตัวแปรของฉันเพื่อแก้ปัญหาข้อ จำกัด ของพื้นที่ที่สามารถดูได้

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

strictBoundsเป็นวัตถุnew google.maps.LatLngBounds()ประเภทหนึ่ง self.gmapจัดเก็บวัตถุ Google Map ( new google.maps.Map())

มันใช้งานได้จริง แต่อย่าลืมคำนึงถึงโรคริดสีดวงทวารด้วยการข้ามเส้นเมอริเดียนที่ 0 และแนวขนานหากขอบเขตของคุณครอบคลุม


ยอมรับว่าอัลกอริทึมของ Daniel Vassallo ทำงานไม่ถูกต้องสำหรับฉัน มีความแตกต่างหลักหลายประการที่นี่
Alexander Palamarchuk

0

ด้วยเหตุผลบางอย่าง

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

ไม่ได้ผลสำหรับฉัน (อาจเป็นปัญหาซีกโลกใต้) ฉันต้องเปลี่ยนเป็น:

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

หวังว่ามันจะช่วยใครสักคน


0

วิธีแก้ปัญหาหนึ่งก็เช่นถ้าคุณรู้ lat / lng ที่เฉพาะเจาะจง

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

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

});

หากไม่มี lat / lng ที่เฉพาะเจาะจง

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

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

});

หรือ

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

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

});

0

ตั้งแต่กลางปี ​​2016ไม่มีวิธีการอย่างเป็นทางการในการ จำกัด พื้นที่ที่สามารถดูได้ โซลูชันเฉพาะกิจส่วนใหญ่ในการ จำกัด ขอบเขตมีข้อบกพร่องเนื่องจากไม่ได้ จำกัด ขอบเขตให้พอดีกับมุมมองแผนที่อย่างแน่นอน แต่จะ จำกัด เฉพาะเมื่อจุดศูนย์กลางของแผนที่อยู่นอกขอบเขตที่กำหนด หากคุณต้องการ จำกัด ขอบเขตในการซ้อนภาพเหมือนฉันอาจทำให้เกิดพฤติกรรมดังที่แสดงด้านล่างโดยที่แผนที่ด้านล่างจะมองเห็นได้ภายใต้ภาพซ้อนทับของเรา:

ป้อนคำอธิบายภาพที่นี่

เพื่อแก้ไขปัญหานี้ฉันได้สร้างไลบรารีซึ่ง จำกัด ขอบเขตได้สำเร็จดังนั้นคุณจึงไม่สามารถเลื่อนออกจากภาพซ้อนทับได้

อย่างไรก็ตามในฐานะโซลูชันอื่น ๆ ที่มีอยู่จะมีปัญหา "สั่น" เมื่อผู้ใช้เลื่อนแผนที่อย่างแรงพอหลังจากปล่อยปุ่มซ้ายของเมาส์แผนที่จะยังคงแพนด้วยตัวเองค่อยๆชะลอตัว ฉันมักจะคืนแผนที่กลับไปที่ขอบเขต แต่นั่นส่งผลให้เกิดการสั่นสะเทือน เอฟเฟกต์การแพนนี้ไม่สามารถหยุดได้ด้วยวิธีการใด ๆ ที่ Js API มีให้ในขณะนี้ ดูเหมือนว่าจนกว่า Google จะเพิ่มการสนับสนุนบางอย่างเช่น map.stopPanningAnimation () เราจะไม่สามารถสร้างประสบการณ์ที่ราบรื่นได้

ตัวอย่างการใช้ไลบรารีที่กล่าวถึงประสบการณ์ขอบเขตที่เข้มงวดที่สุดที่ฉันสามารถได้รับ:

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>

ไลบรารียังสามารถคำนวณการ จำกัด การซูมขั้นต่ำโดยอัตโนมัติ จากนั้นจะ จำกัด ระดับการซูมโดยใช้minZoomแอตทริบิวต์ของแผนที่

หวังว่าสิ่งนี้จะช่วยคนที่ต้องการวิธีแก้ปัญหาที่เคารพขอบเขตที่กำหนดอย่างเต็มที่และไม่ต้องการให้แพนออกจากพวกเขา


-4

นี่อาจเป็นประโยชน์

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

ระดับการซูมสามารถปรับแต่งได้ตามความต้องการ


สิ่งนี้ไม่ได้ตอบคำถามเดิมเกี่ยวกับการ จำกัด ระดับการซูมเป็นช่วงe.g. only between levels 6 and 9แต่จะตั้งค่าระดับการซูมเริ่มต้นและลบ UI เริ่มต้น (เช่น+/ -) ซึ่งเกินความจำเป็นเล็กน้อย
Alastair
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.