Вопрос по google-maps-api-3 – Google Maps API 3 fitBounds padding - убедитесь, что маркеры не скрыты наложенными элементами управления

25

Я хотел бы иметь возможность добавлять отступы к виду карты после вызоваmap.fitBounds()Таким образом, все маркеры могут быть видны независимо от элементов управления карты или таких вещей, как скользящие панели, которые будут открывать маркеры при открытии. Лифлетт имеетвозможность добавить отступы к fitBounds, но Google Maps нет.

Иногда самые северные маркеры частично скрываются над окном просмотра. Самые западные маркеры также часто лежат под ползунком масштабирования. С помощью API 2 можно было сформировать виртуальный видовой экран, уменьшив заданные отступы из видового экрана карты, а затем вызвать методshowBounds() рассчитать и выполнить масштабирование и центрирование на основе этого виртуального видового экрана:

map.showBounds(bounds, {top:30,right:10,left:50});

Рабочий пример этого для API 2 можно найтиВот по ссылке примера showBounds ().

Я не могу найти подобную функциональность в API V3, но, надеюсь, есть другой способ, которым это может быть достигнуто. Может быть, я мог бы взять северо-восточные и юго-западные точки, а затем добавить поддельные координаты, чтобы расширить границы после их включения?

UPDATE

(Codepen в случае, если приведенный ниже код не работает)

function initMap() {
  var map = new google.maps.Map(document.getElementById('map'), {
    draggable: true,
    streetViewControl: false,
    zoomControl: false
  });

  var marker1 = new google.maps.Marker({
    position: {lat: 37, lng: -121},
    map: map,
  });

  var marker2 = new google.maps.Marker({
    position: {lat: 39.3, lng: -122},
    map: map,
  });
 
  var bounds = new google.maps.LatLngBounds();
  bounds.extend(marker1.position);
  bounds.extend(marker2.position);
  map.fitBounds(bounds);
}
#map {
  height: 640px;
  width: 360px;
}
#overlays {
  position: absolute;
  height: 50px;
  width: 340px;
  background: white;
  margin: -80px 10px;
  text-align: center;
  line-height: 50px;
}
/* Optional: Makes the sample page fill the window. */
html, body {
  height: 100%;
  margin: 0;
  padding: 0;
}
<html>
  <head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <title>Simple markers</title>

  </head>
  <body>
    <div id="map"></div>
    <div id="overlays">Controls / Order pizza / ETA / etc.</div>
  
    <script async defer
    src="https://maps.googleapis.com/maps/api/js?&callback=initMap">
    </script>
  </body>
</html>

Проблема заключается в следующем:

enter image description here

Я пытался добавить элемент управления, как описано вПользовательские элементы управления, но карта точно не знает об этом - см.эта скрипка раздвоенный отПример пользовательского элемента управления Maps, Один из маркеров все еще скрыт контролем.

Ваш Ответ

7   ответов
1

Если у нас есть позиция, например,marker.getPosition()мы можем найти другую позицию(x, y) пиксель от него с помощью этой функции.

function extendedLocation(position, x, y) {
    var projection = map.getProjection();
    var newMarkerX = projection.fromLatLngToPoint(position).x + x/(Math.pow(2, map.getZoom()))
    var newMarkerY = projection.fromLatLngToPoint(position).y + y/(Math.pow(2, map.getZoom()))
    var newMarkerPoint = new google.maps.Point(newMarkerX, newMarkerY);
    return projection.fromPointToLatLng(newMarkerPoint)
}

Примечание: положительный х в правильном направлении и положительный у в направлении вниз. Таким образом, в общем случае, чтобы увидеть маркер, нам нужно передать отрицательное значение y, например.extendedLocation(marker.getPosition(), 4, -18)

Если у вас есть постоянный ползунок или любой такой элемент в верхней части, предположительно, высотой 30 пикселей, просто используйтеy параметр в функции как-30.

Можно создать более обобщенную функцию, которая возвращает массив из 4 точек, каждая(x, y) пикселей от заданного направления вверх, вниз, вправо и влево.

function getAllExtendedPosition(position, x, y){
   var positionArray = [];
   postitionArray.push(extendedLocation(position, x, y);
   postitionArray.push(extendedLocation(position, -x, -y);
   postitionArray.push(extendedLocation(position, -x, y);
   postitionArray.push(extendedLocation(position, x, -y);
   return positionArray
}
8

Updated

t; парам вfitBounds метод (с версии 3.32, поправьте меня, если раньше).

У меня еще не было возможности протестировать его, но если вы сможете обновить его, я бы порекомендовал использовать нативный способ. Если вы используете версию & lt; 3.32 и не могу обновить - мое решение для вас.

я взялрабочий раствор отerzzo и немного его улучшил.
Example

fitBoundsWithPadding(googleMapInstance, PolygonLatLngBounds, {left:250, bottom:10});

Описание аргументов:

gMap - google map instance bounds - google maps LatLngBounds object to fit paddingXY - Object Literal: 2 possible formats: {x, y} - for horizontal and vertical paddings (x=left=right, y=top=bottom) {left, right, top, bottom}

function listing to copy

function fitBoundsWithPadding(gMap, bounds, paddingXY) {
        var projection = gMap.getProjection();
        if (projection) {
            if (!$.isPlainObject(paddingXY))
                paddingXY = {x: 0, y: 0};

            var paddings = {
                top: 0,
                right: 0,
                bottom: 0,
                left: 0
            };

            if (paddingXY.left){
                paddings.left = paddingXY.left;
            } else if (paddingXY.x) {
                paddings.left = paddingXY.x;
                paddings.right = paddingXY.x;
            }

            if (paddingXY.right){
                paddings.right = paddingXY.right;
            }

            if (paddingXY.top){
                paddings.top = paddingXY.top;
            } else if (paddingXY.y) {
                paddings.top = paddingXY.y;
                paddings.bottom = paddingXY.y;
            }

            if (paddingXY.bottom){
                paddings.bottom = paddingXY.bottom;
            }

            // copying the bounds object, since we will extend it
            bounds = new google.maps.LatLngBounds(bounds.getSouthWest(), bounds.getNorthEast());

            // SW
            var point1 = projection.fromLatLngToPoint(bounds.getSouthWest());


            // we must call fitBounds 2 times - first is necessary to set up a projection with initial (actual) bounds
            // and then calculate new bounds by adding our pixel-sized paddings to the resulting viewport
            gMap.fitBounds(bounds);

            var point2 = new google.maps.Point(
                ( (typeof(paddings.left) == 'number' ? paddings.left : 0) / Math.pow(2, gMap.getZoom()) ) || 0,
                ( (typeof(paddings.bottom) == 'number' ? paddings.bottom : 0) / Math.pow(2, gMap.getZoom()) ) || 0
            );

            var newPoint = projection.fromPointToLatLng(new google.maps.Point(
                point1.x - point2.x,
                point1.y + point2.y
            ));

            bounds.extend(newPoint);

            // NE
            point1 = projection.fromLatLngToPoint(bounds.getNorthEast());
            point2 = new google.maps.Point(
                ( (typeof(paddings.right) == 'number' ? paddings.right : 0) / Math.pow(2, gMap.getZoom()) ) || 0,
                ( (typeof(paddings.top) == 'number' ? paddings.top : 0) / Math.pow(2, gMap.getZoom()) ) || 0
            );
            newPoint = projection.fromPointToLatLng(new google.maps.Point(
                point1.x + point2.x,
                point1.y - point2.y
            ));

            bounds.extend(newPoint);

            gMap.fitBounds(bounds);
        }
    }
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
23

fitBoundsВы можете уменьшить масштаб на один уровень, чтобы получить достаточно отступов для маркеров.

Предполагатьmap переменная - это ваша ссылка на объект карты;

map.setZoom(map.getZoom() - 1);
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededvar zoom_level = handler.getMap().getZoom()Error: User Rate Limit Exceededhandler.getMap().setZoom(zoom_level - 1)Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededstackoverflow.com/a/11976581/286486
Error: User Rate Limit Exceeded
-1

ой точки LatLong на расчетное расстояние. У объекта google.maps.LatLngBounds () есть функции для получения точек SouthWest и NorthEast ограничительной рамки, которые можно использовать для вычисления расстояния X миль на север, юг, восток или запад.

Например, если вы пытались переместить маркеры вправо для учета наложенных элементов в левой части карты, вы можете попробовать следующее:

// create your LatLngBounds object, like you're already probably doing
var bounds = new google.maps.LatLngBounds();

// for each marker call bounds.extend(pos) to extend the base boundaries

// once your loop is complete
// *** add a calculated LatLng point to the west of your boundary ***
bounds.extend(new google.maps.LatLng(bounds.getSouthWest().lat(), bounds.getSouthWest().lng() - .9));

// finally, center your map on the modified boundaries
map.fitBounds(bounds);

В приведенном выше примере добавление точки LatLong к границам путем вычитания .9 из долготы самой западной точки перемещает границу примерно на 52 мили дальше на запад.

Общая точка (pos.lng () - 1.0) составляет около 58 миль, поэтому вы можете угадать хорошее расстояние или использовать другой метод для вычисления продольного смещения при определении того, какой тип заполнения вам нужен.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
10

расширив границы карты, добавив в нее значение, достаточное для отображения маркеров.

Во-первых, вам нужно создать вид наложения

var overlayHelper = new google.maps.OverlayView();
overlayHelper.onAdd = function() {};
overlayHelper.onRemove = function() {};
overlayHelper.draw = function() {};
overlayHelper.setMap(map);

Если у вас есть помощник по наложению, вам нужно получить проекцию карты и выполнить расчеты на основе этого.

Обратите внимание, что элемент управления, который у меня есть на моей карте, имеет ширину 420 пикселей и высоту 100% в правой части карты. Вам, очевидно, нужно будет изменить код, чтобы приспособить ваши элементы управления.

var mapCanvas = $("#map_canvas"),
    controlLeft = mapCanvas.width() - 420, // canvas width minus width of the overlayed control
    projection = overlayHelper.getProjection(),
    widestPoint = 0, 
    latlng, 
    point;

// the markers were created elsewhere and already extended the bounds on creation
map.fitBounds(mapBounds);

// check if any markers are hidden behind the overlayed control
for (var m in markers) {
    point = projection.fromLatLngToContainerPixel(markers[m].getPosition());
    if (point.x > controlLeft && point.x > widestPoint) {
        widestPoint = point.x;
    }
}

if (widestPoint > 0) {
    point = new google.maps.Point(
                mapCanvas.width() + (widestPoint - controlLeft), 
                mapCanvas.height() / 2); // middle of map height, since we only want to reposition bounds to the left and not up and down

    latlng = projection.fromContainerPixelToLatLng(point);
    mapBounds.extend(latlng);
    map.fitBounds(mapBounds);
}

Если вы делаете это, когда карта загружается в первый раз, вам нужно будет обернуть это в событие карты, чтобы дождаться простоя. Это позволяет представлению наложения инициализироваться. Не включайте создание помощника по наложению в обратный вызов события.

google.maps.event.addListenerOnce(map, 'idle', function() { <above code> });
11

тр padding в методе fitBounds ().

fitBounds(bounds:LatLngBounds|LatLngBoundsLiteral, padding?:number)

Пожалуйста, обратитесь к документации для получения более подробной информации

https://developers.google.com/maps/documentation/javascript/reference#Map

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededpaddingError: User Rate Limit Exceeded
Error: User Rate Limit Exceededissue trackerError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
4

map.fitBounds() с API V3 с тем же синтаксисом заполнения, как вы упомянули сmap.showBounds().

Просто используяmap.fitBounds(bounds, {top:30,right:10,left:50}); работал на меня.

(это может быть комментарий к сообщению xomena или Roman86, у меня недостаточно репутации, чтобы комментировать)

Похожие вопросы