Подтвердить что ты не робот

Как получить доступ к Google Maps API v3 маркер DIV и его положение пикселей?

Вместо окна информации по умолчанию API Карт Google, я собираюсь использовать другой маркер всплывающей подсказки jQuery. Поэтому мне нужно получить маркер DIV и его положение пикселей.

Но не удалось получить его, потому что для определенного маркера нет идентификатора или класса. Только я могу получить доступ к карте canvas div из объекта-маркера и недокументированного объекта pixelBounds.

  • Как я могу получить доступ к маркеру DIV?
  • Где я могу получить позицию пикселя DIV? Могу ли я преобразовать значение lat-lng в значения пикселей?

== прилагается:

Я также пробовал использовать код ниже, но он не меняется, когда я просматриваю карту.

var marker = new google.maps.Marker({...});
google.maps.event.addListener(marker, 'click', function() {
    var px = this.getMap().getProjection().fromLatLngToPoint(this.getPosition());
    console.log("(" + px.x + "," + px.y + ")");
});
4b9b3361

Ответ 1

Я действительно не понимаю, почему вы хотите получить конкретный div для маркера? Если вы хотите отобразить всплывающую подсказку, тогда вам потребуется только пиксельная позиция маркера (и знание размера маркера и размещения привязки), а не элемент div. Вы всегда можете запускать всплывающую подсказку открытия и закрытия вручную, когда событие происходит на стороне google.maps.

Для получения положения пикселя якоря данного маркера вы можете использовать этот код:

var scale = Math.pow(2, map.getZoom());
var nw = new google.maps.LatLng(
    map.getBounds().getNorthEast().lat(),
    map.getBounds().getSouthWest().lng()
);
var worldCoordinateNW = map.getProjection().fromLatLngToPoint(nw);
var worldCoordinate = map.getProjection().fromLatLngToPoint(marker.getPosition());
var pixelOffset = new google.maps.Point(
    Math.floor((worldCoordinate.x - worldCoordinateNW.x) * scale),
    Math.floor((worldCoordinate.y - worldCoordinateNW.y) * scale)
);

В pixelDistance вы получаете смещение определенного якоря маркера, подсчитанного из левого верхнего угла карты (и вы можете получить его позицию из map.getDiv() div). Почему это работает (или есть лучший способ?), Вы можете прочитать в документацию наложения карт Google.

Ответ 2

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

var proj = overlay.getProjection();
var pos = marker.getPosition();
var p = proj.fromLatLngToContainerPixel(pos);

Теперь вы можете получить доступ к своим пиксельным координатам через p.x и p.y.

СЛЕДУЮЩИЙ ДОБАВЛЕННЫЙ КОММЕНТАРИЙ:

Падение проекции оверлея состоит в том, что до тех пор, пока его холст карты не закончит загрузку, он не инициализируется. У меня есть следующий прослушиватель, который заставит любой метод, который мне нужно вызвать, когда карта закончит загрузку.

google.maps.event.addListener(map, 'idle', functionName());

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

if(overlay.getProjection()) {
  // code here
}

Ответ 3

Одна вещь, которую следует помнить при использовании кода MBO: Когда плитки карты повторяются, map.getBounds().getSouthWest() возвращает "-180" независимо от положения карты. Резервирование, которое я использую в этом случае, вычисляет расстояние пикселя до центра вместо верхнего левого угла, так как map.getCenter(), кажется, возвращает текущую центрированную точку в любом случае. Например. (используя jQuery):

// Calculate marker position in pixels form upper left corner
var pixelCoordsCenter = map.getProjection().fromLatLngToPoint(map.getCenter());
pixelOffset = new google.maps.Point(
    Math.floor((pixelCoordsMarker.x - pixelCoordsCenter.x) * scale + $(container).width()/2),
    Math.floor((pixelCoordsMarker.y - pixelCoordsCenter.y) * scale + $(container).height()/2)
);

Ответ 4

кто-то все еще ищет ответ на этот вопрос, посмотрите здесь: http://code.google.com/p/google-maps-utility-library-v3/wiki/Libraries среди некоторых других полезных карт Google есть материал RichMarker, который позволяет вам добавлять элементы DOM по вашему выбору в качестве перетаскиваемых маркеров. просто добавьте класс /id для обработки с помощью jQuery.

Ответ 5

Ответ Рене дает только "мировые координаты" (т.е. не зависит от уровня масштабирования и окна просмотра). Ответ MBO кажется правильным, тем не менее, так, что тот, который вы должны принять и проголосовать (я не могу, поскольку я только что зарегистрировался), так как решение может быть легко пропущено иначе.

Что касается "более простой" версии, вы можете использовать методы в MapCanvasProjection вместо этого, но это означает, что вам нужно будет сделать свой собственный оверлей. См. здесь для примера.: P

Ответ 6

MapCanvasProjection fromLatLngToContainerPixel(), вероятно, автор. Это даст вам смещение пикселей относительно контейнера карты. Я сделал несколько экспериментов и нашел "самое простое" рабочее решение. (Я хочу, чтобы Google сделала эту функцию более доступной!)

Сначала вы объявляете подкласс OverlayView где-то так:

function CanvasProjectionOverlay() {}
CanvasProjectionOverlay.prototype = new google.maps.OverlayView();
CanvasProjectionOverlay.prototype.constructor = CanvasProjectionOverlay;
CanvasProjectionOverlay.prototype.onAdd = function(){};
CanvasProjectionOverlay.prototype.draw = function(){};
CanvasProjectionOverlay.prototype.onRemove = function(){};

Затем где-то еще в вашем коде, где вы создаете экземпляр карты, вы также создаете экземпляр этого OverlayView и устанавливаете его карту, например:

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

// Add canvas projection overlay so we can use the LatLng to pixel converter
var canvasProjectionOverlay = new CanvasProjectionOverlay();
canvasProjectionOverlay.setMap(map);

Затем, когда вам нужно использовать fromLatLngToContainerPixel, вы просто делаете это:

canvasProjectionOverlay.getProjection().fromLatLngToContainerPixel(myLatLng);

Обратите внимание, что поскольку объект MapCanvasProjection будет доступен только после вызова draw(), который когда-то был перед картой idle, я предлагаю создать логический флаг "mapInitialized", установить его на true на первой карте idle обратный вызов. И затем сделайте то, что вам нужно сделать только после этого.

Ответ 7

Хорошо, если вы ДОЛЖНЫ получить доступ к DIV, вот какой-то код. Помните, что это будет работать только со стандартным маркером (20x34px), и он найдет все маркеры. Возможно, вам захочется улучшить этот хак в соответствии с вашими потребностями...

BEWARE! ЭТО ХУХ

var a=document.getElementById('map_canvas');
var b=a.getElementsByTagName('img');
var i, j=b.length;
for (i=0; i<j; i++) {
  if(b[i].src.match('marker_sprite.png')){
    if(b[i].style.width=='20px' && b[i].style.height=='34px') {
      c=b[i].parentElement;
      console.log(c.style.top+":"+c.style.left);
      // this is a marker enclosing div

    }
  }
}

Ответ 8

Рабочий фрагмент jQuery, готовый для копирования/вставки:

шаг 1 - инициализировать карту и параметры

<html>
<head>
<script src="get-your-jQuery" type="text/javascript"></script>
<script src="get-your-maps.API" type="text/javascript"></script>
<script type="text/javascript">
<!--
$(document).ready(function(){
var bucharest = new google.maps.LatLng(44.43552, 26.10250);
var options = {
zoom: 14,
center: bucharest,
mapTypeId: google.maps.MapTypeId.ROADMAP 
}

Как вы можете видеть, ниже, переменной карте не предшествует VAR, потому что она должна быть глобальной, поскольку мы используем другую функцию для получения fromLatLngToContainerPixel. Подробнее см. closures.

map = new google.maps.map($("#map_canvas")[0], options);

var marker = new google.maps.Marker({
position: google.maps.LatLng(44.4407,26.0864),
map: map
});

new google.maps.event.addListener(marker, 'mouseover', function(){
          placeMarker( marker.getPosition(),'#tooltip');//param1: latlng, param2: container to place result
});

new google.maps.event.addListener(map, 'bounds_changed', function(){
        $("#tooltip").css({display:'none'}); //this is just so you can see that all goes well ;)
    });

 overlay = new google.maps.OverlayView();
 overlay.draw = function() {};
 overlay.setMap(map);

}); //here ends jQuery.ready

function placeMarker(location, ID){
var containerPixel = overlay.getProjection().fromLatLngToContainerPixel(location);
var divPixel       = overlay.getProjection().fromLatLngToDivPixel(location);
$(ID).css({top:containerPixel.y, left:containerPixel.x, 'dislay':'block'});
}
//--> 
</script>
</head>
<body>
<div id="tooltip" style="width:100px; height:100px; position:absolute; z-index:1; background:#fff">Here I am!</div>
<div id="map_canvas" style="width:300px; height:300px"></div>
</body>
</html>

Ответ 9

Мне было проще назначить пользовательский значок и использовать атрибут img src для доступа к элементу. Вы все равно можете использовать значок карты Google по умолчанию, просто сохраните его локально.

$("#map img[src='my_marker.png']").getBoundingClientRect();

Ответ 10

Для многих обстоятельств сложная математика, используемая для расчета и изменения положения штифта в принятом ответе, может быть уместна.

Для моего конкретного использования я просто создал прозрачный PNG с холстом, значительно большим, чем мне нужно для значка. Затем я просто экспериментировал, перемещая булавку вокруг прозрачного фона и применяя новое изображение к карте.

настройка смещения булавки в фотошопе

Вот спецификация для добавления пользовательского пин-изображения с примерами: https://developers.google.com/maps/documentation/javascript/examples/icon-simple

Этот метод определенно масштабируется как смещение в пикселях вместо фактического разного длинного/лат, даже если вы увеличиваете масштаб.