Вопрос по google-maps-api-3, javascript – Google Maps InfoBubble pixelOffset (перемещение от позиции по умолчанию над маркером)

14

Я пытаюсь реализовать собственный инфо-пузырь, у которого окно будет открываться сбоку от маркера, а не по умолчанию сверху. Это оказалось сложнее, чем ожидалось.

Используя обычное информационное окно, вы можете использовать pixelOffset. Смотрите здесь длядокументаци

Использование infoBubble, похоже, не так. Есть ли возможность использовать pixelOffset в infoBubble или что-то подобное?

Я обнаружил, что это очень трудно найти, так как использование поиска Google, такого как этот, не дает релевантных результатовПоиск Гуг

Ниже приведены все мои ресурсы, которые я использовал.

Пример infoBubbleВо.

Мой JavaScript для настройки карты и infoBubbleВо.

А теперь мой javascript здесь только в случае, если ссылка jsfiddle не работает.

<script type="text/javascript">

    $(document).ready(function () {
        init();
    });

    function init() {

        //Setup the map
        var googleMapOptions = {
            center: new google.maps.LatLng(53.5167, -1.1333),
            zoom: 13,
            mapTypeId: google.maps.MapTypeId.ROADMAP
        };

        //Start the map
        var map = new google.maps.Map(document.getElementById("map_canvas"),
        googleMapOptions);

        var marker = new google.maps.Marker({
            position: new google.maps.LatLng(53.5267, -1.1333),
            title: "Just a test"
        });

        marker.setMap(map);

        infoBubble = new InfoBubble({
            map: map,
            content: '<div class="phoneytext">Some label</div>',
            //position: new google.maps.LatLng(-35, 151),
            shadowStyle: 1,
            padding: '10px',
            //backgroundColor: 'rgb(57,57,57)',
            borderRadius: 5,
            minWidth: 200,
            arrowSize: 10,
            borderWidth: 1,
            borderColor: '#2c2c2c',
            disableAutoPan: true,
            hideCloseButton: false,
            arrowPosition: 7,
            backgroundClassName: 'phoney',
            pixelOffset: new google.maps.Size(130, 120),
            arrowStyle: 2
        });
        infoBubble.open(map, marker);

    }
</script>

Обновит

Чтобы помочь с ответом на этот вопрос, я собрал тестовый примерВо. Важными строками являются строки 38 и 39, которые должны указывать, где разместить метку.

Обновление 2

Для получения награды мне нужно увидеть пример информационного пузыря, расположенного далеко от позиции по умолчанию над маркером. Желательно с правой стороны маркера.

Обновление 3

Я удалил тестовый пример из обновления 1, поскольку он размещен на серверах моей старой компании.

Похоже, это может сработать, да Undefined
просто мозговой штурм: если вы знаете положение маркера: (lng, lat), то (lng + X, lat) должно быть позицией для пузыря, верно? Gavriel

Ваш Ответ

6   ответов
1

но нигде не смог найти ответа. Путем небольшой проб и ошибок я решил это.

Вы будете использовать файл Google JS для "infoBubble". Зайдите в этот файл и найдите ...

InfoBubble.prototype.buildDom_ = function() {

Для меня это в строке 203 (но это может быть результатом предыдущих перетасовок и правок).

Внутри этой функции вы увидите положение «абсолютное». декларация. В новой строке вы можете добавить marginTop, marginRight, marginBottom и marginLeft. Это отодвинет пузырь от его позиции по умолчанию (которая также зависит от объявления позиции стрелки в вашей конфигурации) ...

Это мой код в файле пузыря JS, который помещает пузырек поверх маркера (из-за особенностей дизайна) ...

var bubble = this.bubble_ = document.createElement('DIV');
bubble.style['position'] = 'absolute';
bubble.style['marginTop'] = this.px(21);
bubble.style['marginLeft'] = this.px(1);
bubble.style['zIndex'] = this.baseZIndex_;

Надеюсь, это поможет.

1

В функцию buildDom InfoBubble добавьте:

bubble.className = 'bubble-container';

Теперь у вас есть класс CSS для каждого InfoBubble, вы можете переместить его с помощью поля CSS.

если вы используете сжатый JS найтиfunction m(a){var c=a.c=document.createElement("DIV"); затем добавьтеc.className='bubble-container';
1

Вы также можете использовать определенную высоту якоря;

var anchorHeight = YOURNUMBER;

строка 874 infobubble.js

9

ВInfoBubble библиотека

замещать

всеInfoBubble.prototype.draw  метод

с

/*
 * Sets InfoBubble Position
 * */
InfoBubble.prototype.setBubbleOffset = function(xOffset, yOffset) {
  this.bubbleOffsetX = parseInt(xOffset);
  this.bubbleOffsetY = parseInt(yOffset);
}


/*
 * Gets InfoBubble Position
 * */
InfoBubble.prototype.getBubbleOffset = function() {
  return {
    x: this.bubbleOffsetX || 0,
    y: this.bubbleOffsetY || 0
  }
}

/**
 * Draw the InfoBubble
 * Implementing the OverlayView interface
 */
InfoBubble.prototype.draw = function() {
  var projection = this.getProjection();

  if (!projection) {
    // The map projection is not ready yet so do nothing
    return;
  }

  var latLng = /** @type {google.maps.LatLng} */ (this.get('position'));

  if (!latLng) {
    this.close();
    return;
  }

  var tabHeight = 0;

  if (this.activeTab_) {
    tabHeight = this.activeTab_.offsetHeight;
  }

  var anchorHeight = this.getAnchorHeight_();
  var arrowSize = this.getArrowSize_();
  var arrowPosition = this.getArrowPosition_();

  arrowPosition = arrowPosition / 100;

  var pos = projection.fromLatLngToDivPixel(latLng);
  var width = this.contentContainer_.offsetWidth;
  var height = this.bubble_.offsetHeight;

  if (!width) {
    return;
  }

  // Adjust for the height of the info bubble
  var top = pos.y - (height + arrowSize) + this.getBubbleOffset().y;

  if (anchorHeight) {
    // If there is an anchor then include the height
    top -= anchorHeight;
  }

  var left = pos.x - (width * arrowPosition) + this.getBubbleOffset().x;

  this.bubble_.style['top'] = this.px(top);
  this.bubble_.style['left'] = this.px(left);

  var shadowStyle = parseInt(this.get('shadowStyle'), 10);

  switch (shadowStyle) {
    case 1:
      // Shadow is behind
      this.bubbleShadow_.style['top'] = this.px(top + tabHeight - 1);
      this.bubbleShadow_.style['left'] = this.px(left);
      this.bubbleShadow_.style['width'] = this.px(width);
      this.bubbleShadow_.style['height'] =
        this.px(this.contentContainer_.offsetHeight - arrowSize);
      break;
    case 2:
      // Shadow is below
      width = width * 0.8;
      if (anchorHeight) {
        this.bubbleShadow_.style['top'] = this.px(pos.y);
      } else {
        this.bubbleShadow_.style['top'] = this.px(pos.y + arrowSize);
      }
      this.bubbleShadow_.style['left'] = this.px(pos.x - width * arrowPosition);

      this.bubbleShadow_.style['width'] = this.px(width);
      this.bubbleShadow_.style['height'] = this.px(2);
      break;
  }
};

и тогда вы можете использовать это

var infoBubble = new InfoBubble({
  map: map,
  content: "My Content",
  position: new google.maps.LatLng(1, 1),
  shadowStyle: 1,
  padding: 0,
  backgroundColor: 'transparent',
  borderRadius: 7,
  arrowSize: 10,
  borderWidth: 1,
  borderColor: '#2c2c2c',
  disableAutoPan: true,
  hideCloseButton: true,
  arrowPosition: 50,
  backgroundClassName: 'infoBubbleBackground',
  arrowStyle: 2

});

Тогда, наконец, мы должны использовать этот методsetBubbleOffset(x,y); установить позицию InfoBubble

infoBubble.setBubbleOffset(0,-32);
1

в InfoBubble нет такой опции, как pixelOffset. Но если вы просто хотите поднять Bubble выше маркера в вашем примере, вам не следует устанавливатьmap параметр при пузырьковой инициализации. Рассмотрим следующую скрипку (я исправил это для вас):

http://jsfiddle.net/ssrP9/5/

Постскриптум Ваша скрипка не работает, потому что вы не добавили ресурсы должным образом http://doc.jsfiddle.net/basic/introduction.html#add-resources

Спасибо за это jsfiddle, я включу это в свой вопрос. К сожалению, я ищу размещение информационного пузыря в другом положении над маркером Undefined
Забыл упомянуть. Мой ответ основан на анализе источников. Поэтому, если вам действительно нужно установить пользовательское смещение относительно маркера, есть два способа: 1. Получить источники этой библиотеки и добавить необходимую функциональность 2. [Довольно странно] Поместить невидимый маркер с необходимым смещением от оригинала и открыть пузырь для него.
9

что библиотека infoBubble по умолчанию позиционирует пузырь над маркером, с которым он связан. Посмотрите на пример файла, который они включили в библиотеку:http://code.google.com/p/google-maps-utility-library-v3/source/browse/trunk/infobubble/examples/example.html , В частности, обратите внимание на строку 99 и строку 122 и использование двух инфопузырьков. Первый связан с маркером, однако второй является автономным, и, таким образом, если вы видите линию 106, вы можете определить позицию для него. Теперь, основываясь на этом понимании, я создал для вас пример в этой скрипкеhttp://jsfiddle.net/pDFc3/, Инфо-пузырь расположен справа от маркера.

Это странно, потому что в js-библиотеке infoBubble есть функция для setPosition (http://code.google.com/p/google-maps-utility-library-v3/source/browse/trunk/infobubble/src/infobubble.js?r=206 ) см. строку 1027. Но по какой-то причине после того, как я дождусь загрузки DOM и попытаюсь изменить положение, перейдяinfoBubble.setPosition(newLatLng); Я не работаю. Наоборот, декларируяinfoBubble.getPosition(); после загрузки DOM выдает текущую позицию маркера, к которому привязан инфо-пузырь. Поэтому setPosition () может иметь ошибку в библиотеке js, потому что я считаю, что она все еще работает (возможно, я ошибаюсь, возможно, она просто глючит).

Я исправил свой jsFiddle, чтобы решить вашу проблему при увеличении и уменьшении масштаба и соответственно позиционировании информационного пузыря (http://jsfiddle.net/pDFc3/ ). Позвольте мне сначала объяснить логику. Во-первых, максимальный уровень масштабирования в Картах Google для типа дорожной карты равен 21 - это значение несовместимо для спутниковых изображений, но максимальное увеличение, к которому пользователь может перейти, составляет 21. Начиная с 21 каждый раз, когда вы уменьшаете масштаб, различия между двумя точками могут быть поддерживается в неизменном виде "на экране" основан на следующей логике:

consitent_screen_dist = initial_dist * (2 ^ (21 - zoomlevel))

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

var newlong = marker.getPosition().lng() + (0.00003 * Math.pow(2, (21 - map.getZoom())));

Аналогично, чтобы гарантировать, что расстояние остается постоянным при каждом изменении уровня масштабирования, мы просто объявляем новую долготу при прослушивании изменения уровня масштабирования:

    google.maps.event.addListener(map, "zoom_changed", function() {
        newlong = marker.getPosition().lng() + (0.00003 * Math.pow(2, (21 - map.getZoom())));
        infoBubble.setPosition(new google.maps.LatLng(marker.getPosition().lat(), newlong));                
    });

Помните, что вы можете сделать этот код гораздо более эффективным, объявив переменные для marker.getPosition и других значений, которые вызываются через методы. Так что вызовы метода не повторяются и замедляют ваш код.

Это то, что я ищу, одна проблема заключается в том, что при увеличении и уменьшении маркер перемещается относительно маркера, иногда скрывая его полностью. Как вы думаете, это то, что можно решить? Undefined
Я обновил ответ и мой jsFiddle, пожалуйста, посмотрите, я думаю, что это решает вашу проблему.
Это верно, потому что мы устанавливаем положение информационного пузыря относительно маркера на определенном уровне масштабирования. Но после изменения уровня масштабирования расстояние между маркером и информационным пузырем (разница между координатами широты и долготы обоих) не меняется. Поэтому, когда вы уменьшаете масштаб, эта разница настолько мала, что вы видите инфо-пузырь поверх маркера.
Однако эта проблема решена, но я обнаружил, что если вы не привязываете infoBubble к создателю, тогда вы можете использовать метод infoBubble.setPosition (latlng). Это означает, что мы можем прослушивать изменения масштаба с помощью прослушивателя событий карт Google.zoom_changed а затем использоватьgetZoom() функция для определения классов, как позиционировать инфо-пузырь относительно маркера на основе уровней масштабирования. Я обновлю свой jsfiddle этим возможным исправлением, но не стесняйтесь экспериментировать, основываясь на этом принципе.

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