Google Maps InfoBubble pixelOffset (переход от позиции по умолчанию над маркером)
Я пытаюсь реализовать пользовательский infoBubble, который имеет окно, открывающееся в сторону маркера, а не позицию по умолчанию сверху. Это оказалось сложнее, чем ожидалось.
Используя обычный инфо-окно, вы можете использовать pixelOffset. См. Здесь documentation
Использование infoBubble, похоже, не так. Есть ли способ использования pixelOffset в infoBubble или что-то, что будет делать то же самое?
Я нашел это очень трудным для поиска, поскольку использование поиска Google, такого как это, не возвращает никаких релевантных результатов Google Search
Ниже приведены все мои ресурсы, которые я использовал.
И теперь мой 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
Чтобы награда была присуждена, мне нужно увидеть пример infoBubble, расположенный вдали от позиции по умолчанию над маркером. Предпочтительно, чтобы правая сторона маркера.
Обновление 3
Я удалил тестовый файл из обновления 1, потому что он размещен на моих старых серверах компании.
Ответы
Ответ 1
Кажется, что сама библиотека 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/. Информационная панель расположена справа от маркера.
Странно, потому что библиотека infoBubble js имеет функцию 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 дает мне текущую позицию маркера, к которой привязан infoBubble. Поэтому setPosition() может иметь ошибку в js-библиотеке, потому что я считаю, что она все еще работает (я могу ошибаться, может быть, это просто глючит).
Я исправил свой jsFiddle, чтобы решить вашу проблему при масштабировании и выключении, и соответственно позиционируя infoBubble (http://jsfiddle.net/pDFc3/). Позвольте мне сначала объяснить логику. Во-первых, максимальный уровень масштабирования на Картах Google для типа дорожной карты равен 21 - это значение не соответствует спутниковым снимкам, но максимальный масштаб, на который может перейти пользователь, равен 21. Начиная с 21, каждый раз, когда вы уменьшаете масштаб, разница между двумя точками может быть последовательно "на экране" на основе следующей логики:
consitent_screen_dist = initial_dist * (2 ^ (21 - zoomlevel))
В нашем случае разумное значение для начального расстояния составляло 0,00003 градуса (между маркером и infoBubble). Итак, основываясь на этой логике, я добавил следующую часть, чтобы найти начальное продольное расстояние между маркером и infoBubble:
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 и другие значения, вызванные методами. Так что вызовы метода не повторяются и замедляют ваш код.
Ответ 2
Это мое решение.
В 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);
Ответ 3
К сожалению, такой опции, как pixelOffset в InfoBubble, отсутствует. Но если вы просто хотите переместиться вверх по Bubble над маркером в своем примере, вы не должны устанавливать параметр map при инициализации пузырьков. Рассмотрим следующую скрипту (я исправил ее для вас):
http://jsfiddle.net/ssrP9/5/
P.S. Ваша скрипка не работает, потому что вы не добавили ресурсы должным образом
http://doc.jsfiddle.net/basic/introduction.html#add-resources
Ответ 4
Я только что столкнулся с одной и той же проблемой, но не смог найти ответ нигде. Сквозь небольшой проб и ошибок я справился.
Вы будете использовать JS файл Google для "infoBubble". Зайдите в этот файл и выполните поиск...
InfoBubble.prototype.buildDom_ = function() {
Для меня это в строке 203 (но это может быть результатом предыдущих перетасовки и редактирования).
Внутри этой функции вы увидите позицию "абсолютное" объявление. В новой строке вы можете добавить marginTop, marginRight, marginBottom и marginLeft. Это подтолкнет пузырь от положения по умолчанию (которое также зависит от объявления позиции стрелки в вашей конфигурации)...
Это моя настройка кода в JSP файле пузыря, который позиционирует пузырь поверх метки (из-за функции дизайна)...
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_;
Надеюсь, что это поможет.
Ответ 5
Вы также можете использовать определенную высоту привязки;
var anchorHeight = YOURNUMBER;
строка 874 infobubble.js
Ответ 6
В функции CreateDom InfoBubble добавьте:
bubble.className = 'bubble-container';
Теперь у вас есть класс CSS для каждого InfoBubble, вы можете перенести его с помощью поля CSS.