Google Maps v3 fitBounds () ซูมใกล้เกินไปสำหรับเครื่องหมายเดียว


93

มีวิธีตั้งค่าระดับการซูมสูงสุดสำหรับfitBounds()? ปัญหาของฉันคือเมื่อแผนที่ถูกป้อนเพียงตำแหน่งเดียวมันจะซูมเข้าไปเท่าที่จะทำได้ซึ่งทำให้แผนที่ไม่อยู่ในบริบทและทำให้มันไร้ประโยชน์ บางทีฉันอาจใช้แนวทางที่ผิด?

ขอบคุณล่วงหน้า!


2
stackoverflow.com/questions/4523023/…เป็นทางออกที่ดีกว่ามาก โดยเฉพาะ @Nequins answer
Kennet

คำตอบ:


139

ฉันชอบวิธีแก้ปัญหาของ mrt (โดยเฉพาะอย่างยิ่งเมื่อคุณไม่รู้ว่าคุณจะทำแผนที่หรือปรับจุดกี่จุด) ยกเว้นว่าจะปิดเครื่องหมายเพื่อไม่ให้อยู่ตรงกลางแผนที่อีกต่อไป ฉันแค่ขยายมันโดยจุดเพิ่มเติมลบ. 01 จาก lat และ lng เช่นกันดังนั้นมันจึงทำให้มาร์กเกอร์อยู่ตรงกลาง ใช้งานได้ดีขอบคุณ 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
ความคิดที่ดีในการรักษาศูนย์กลางเดิม สาเหตุที่ไม่สามารถปรับระดับการซูมได้อย่างน่าเชื่อถือเมื่อใช้fitBounds()วิธีนี้เนื่องจากการซูมเกิดขึ้นแบบอะซิงโครนัส: stackoverflow.com/questions/2989858/…
Metro Smurf

1
สิ่งนี้ได้ผลดีสำหรับฉัน ฉันต้องส่งการอ้างอิงแผนที่ไปยังฟังก์ชัน "ฟังก์ชัน fitToMarkers (เครื่องหมาย, แผนที่)" บน V3 แต่หลังจากนั้นก็ใช้งานได้อย่างมีเสน่ห์!
เชน

4
รักมัน. ดี @ryan ใช้งานได้ดีสำหรับฉัน แต่. 01 ในกรณีของฉันซูมออกไปไกลเกินไป. 001 ก็โดนจุดหวาน
willdanceforfun

ขอบคุณ. Like @willdanceforfun กรณีเดียวกัน 001 โดนใจ
Goran Jakovljevic

1
ฉันอยากจะแนะนำวิธีแก้ปัญหานี้stackoverflow.com/questions/2437683/…
NinjaOnSafari

40

คุณสามารถตั้งค่าแผนที่ของคุณได้maxZoomในMapOptions (api-reference)ดังนี้:

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

วิธีนี้จะป้องกันไม่ให้แผนที่ซูมลึกลงไปเมื่อใช้งานfitBounds()และยังลบระดับการซูมออกจากตัวควบคุมการซูม


@candlejack ตรงตามที่อธิบายไว้ในคำตอบของฉันหรือไม่?
Flygenring

8
คุณสามารถตั้งค่าmaxZoomก่อนที่จะกระชับขอบเขตแล้วยกเลิกการตั้งค่าอีกครั้งโดยใช้map.setOptions({ maxZoom: undefined })กับidleเหตุการณ์ที่เริ่มทำงานโดยการเปลี่ยนขอบเขต ซึ่งจะป้องกันไม่ให้เอฟเฟกต์การซูมเข้าการซูมออกของการรีเซ็ตการซูมในidleเหตุการณ์แทน
El Yobo

29

อีกวิธีหนึ่งคือการขยายขอบเขตหากคุณตรวจพบว่ามีขนาดเล็กเกินไปก่อนที่คุณจะดำเนินการ 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 });

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


สุดยอด! ประหยัดชีวิต!
Jaypee

18

เมื่อคุณเพิ่มขอบเขตจริงทั้งหมดแล้วให้เพิ่มบรรทัดเหล่านี้

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

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

สิ่งนี้ตั้งค่าการซูมขั้นต่ำอย่างมีประสิทธิภาพเปลี่ยนค่าออฟเซ็ตเพื่อเพิ่มหรือลดการซูม


12

หากเป็นสถานที่เดียวคุณสามารถใช้ setCenter () และ setZoom () แทนได้


ทางออกที่ง่ายที่สุด
Alberto M

11

คุณสามารถใช้

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

ด้วยวิธีนี้คุณตั้งค่าคุณสมบัติของแผนที่หลังจากที่แผนที่ได้รับการเริ่มต้นแล้ว .... คุณสามารถตั้งค่าได้หลายครั้งตามที่คุณต้องการ ... แต่ในกรณีของคุณ ... คุณสามารถตั้งค่าก่อนที่จะ fitBounds ()

ขอให้โชคดี rarutu


7

วิธีที่ฉันป้องกันไม่ให้แผนที่ขยายออกไปไกลคือการเพิ่มโค้ดบรรทัดนี้:

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

หลังจากบรรทัดนี้โดยตรง:

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

อย่าลังเลที่จะเปลี่ยนระดับการซูมเป็นระดับใดก็ได้ที่คุณไม่ต้องการให้แผนที่ซูมผ่านมา

หากคุณมีปัญหาหรือคำถามใด ๆ เพียงแสดงความคิดเห็นในบล็อกโพสต์ที่ฉันเขียนเกี่ยวกับเรื่องนี้ที่http://icode4you.net/creating-your-own-store-locator-map-how-to-prevent-the- map-from-zooming-in-too-close-on-a-marker


1
ฉันชอบวิธีนี้ แต่ใส่ setzoom ไว้ข้างใน if เพื่อไม่เรียกมันทุกครั้ง นอกจากนี้ยังอาจมีผลข้างเคียงของเวลาที่ส่งคืน 'ไม่ได้กำหนด' จาก getzoom () วิธีแก้ไข: zoom = map.getZoom (); ถ้า (typeof zoom! == 'undefined' && zoom> 8) map.setZoom (8);
Le Droid

5

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

ต่อไปนี้เป็นวิธีตรวจสอบก่อนว่าจุดนั้นอยู่ในระยะห่างที่กำหนดไว้หรือไม่จากนั้นหากมีขนาดเล็กกว่าระยะทางต่ำสุดให้ขยายขอบเขตตามระยะทางขั้นต่ำนั้น:

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

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


3

สิ่งนี้ช่วยให้คุณควบคุมได้โดยตรงเมื่อซูมสูงสุดที่อนุญาตในขอบเขตที่เหมาะสม

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

สำหรับฉันพวกฉันแก้ปัญหาด้วยการสร้างเหตุการณ์ที่ไม่ได้ใช้งานหลังจาก fitBounds ทำงานได้อย่างสมบูรณ์ เดาว่าเป็นหนึ่งในโซลูชั่นที่สะอาดที่สุดที่นี่

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

ฉันแก้ไขด้วยส่วนนี้เนื่องจาก Google Maps V3 ขับเคลื่อนด้วยเหตุการณ์:

คุณสามารถบอก API ให้ตั้งค่าการซูมกลับเป็นจำนวนที่เหมาะสมเมื่อเหตุการณ์zoom_changedทริกเกอร์:

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

ฉันใช้Intialทำให้แผนที่ไม่ซูมโหลดมากเกินไปเมื่อ fitBounds ในที่สุดอนุญาตโดยที่เหตุการณ์การซูมเกิน 11 จะเป็นไปไม่ได้สำหรับผู้ใช้


1

หลังจากfitBounds()วิธีการโทรลองตั้งค่าระดับการซูมอีกครั้ง มันจะบังคับให้แผนที่อยู่ในระดับการซูมนั้นในขณะที่อยู่กึ่งกลางในตำแหน่งที่ถูกต้อง


0

ฉันมีจิตวิญญาณตามการ จำกัด การซูมสูงสุดเมื่อพอดีกับขอบเขต ใช้งานได้สำหรับฉัน (ทดสอบบน 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

และ .. นี่คืออีกหนึ่ง
ความคิดเดียวกันกับ mrt และ Ryan แต่

  • ยังใช้งานได้หากขนาดขอบเขตไม่ตรงกับศูนย์ (*)
  • ป้องกันความผิดเพี้ยนใกล้เสา
  • ใช้ getCenter () แทน getNorthEast ()

(*) หมายเหตุ: หากกล่องใหญ่พออยู่แล้วการเพิ่มคะแนนพิเศษทั้งสองนั้นจะไม่มีผล ดังนั้นเราจึงไม่จำเป็นต้องตรวจสอบเพิ่มเติม

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

แก้ไข: ฉันไม่แน่ใจว่าการคำนวณอัตราส่วนของฉันถูกต้องหรือไม่เนื่องจากเรามีการคาดการณ์ของ Mercator ฉันอาจแก้ไขสิ่งนี้ใหม่ ..


0

มีคำตอบแล้วที่นี่Google Maps v3: บังคับใช้ขั้นต่ำ ระดับการซูมเมื่อใช้ fitBoundsมันทำงานได้ตามที่คาดไว้ :) ดังนั้นตอนนี้ถ้าหลังจากที่พอดีขอบเขตการซูมน้อยกว่าให้บอกว่า 13 คุณสามารถตั้งค่าการซูมใหม่ที่คุณต้องการได้


-1

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

เอฟเฟกต์อีกครั้งทำให้มั่นใจได้ถึงการซูมสูงสุดโดยไม่ต้องใช้ตัวเลือก maxZoom ซึ่งอาจมีผลที่ไม่ต้องการทำให้ผู้ใช้ไม่สามารถซูมได้ไกลกว่าระดับสูงสุดซูมด้วยการควบคุมการซูม

ฉันได้คำนวณ maxLat, minLat, maxLng และ 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,
});
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.