如何访问Google Maps API v3标记的DIV及其像素位置?

时间:2010-04-20 10:49:07

标签: google-maps google-maps-api-3

我将使用其他jQuery工具提示插件而不是Google Maps API的默认信息窗口。所以我需要得到标记的DIV及其像素位置。

但无法得到它,因为某些标记没有id或class。只有我可以从标记对象和未记录的pixelBounds对象访问地图画布div。

  1. 如何访问标记的DIV?
  2. 我在哪里可以获得DIV的像素位置?我可以将lat-lng位置转换为像素值吗?
  3. == 所附:

    我也试过下面的代码,但滚动地图时它没有改变。

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

11 个答案:

答案 0 :(得分:48)

我真的不明白你为什么要为标记获得特定的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获取它的位置)。为什么它会像这样工作(或者有更好的方法吗?),你可以阅读documentation of google maps overlays

答案 1 :(得分:10)

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
}

答案 2 :(得分: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)
);

答案 3 :(得分:2)

任何人仍在寻找答案,请看一下:http://code.google.com/p/google-maps-utility-library-v3/wiki/Libraries 在其他一些有用的谷歌地图中,​​RichMarker允许您添加您选择的DOM元素作为可拖动标记。只需使用jQuery添加class / id即可。

答案 4 :(得分:1)

Rene的答案仅为您提供“世界坐标”(即,与缩放级别和视口无关的坐标)。 MBO的回答似乎是正确的,所以这是你应该接受和投票的那个(我不能像我刚刚注册的那样)因为解决方案可能很容易被忽视。

对于“更简单”的版本,您可以使用MapCanvasProjection中的方法,但这意味着您必须制作自己的叠加层。有关示例,请参阅here。 :P

答案 5 :(得分:1)

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回调。然后在那之后做你需要做的事。

答案 6 :(得分:1)

好吧,如果你必须访问DIV,这里有一些代码。请注意,这只适用于标准标记(20x34px),并且它会找到所有标记。您可能希望改进此黑客以满足您的需求......

<强>小心!这是一个黑客

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's enclosing div

    }
  }
}

答案 7 :(得分:0)

准备复制/粘贴的工作代码段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 
}

正如你所看到的那样,变量map之前没有VAR,因为它应该是Global,因为我们使用另一个函数来获取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>

答案 8 :(得分:0)

我发现最简单的方法是分配自定义图标并使用img src属性来获取元素。您仍然可以使用默认的Google地图图标,只需将其保存在本地。

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

答案 9 :(得分:0)

对于许多情况,复杂的数学使用计算并在接受的答案中更改引脚位置可能是合适的。

对于我的特殊用途,我刚创建了一个透明的PNG,其画布明显大于我所需的图标。然后我只是尝试在透明背景中移动图钉并将新图像应用到地图上。

adjusting the pin offset in photoshop

以下是添加自定义图片图片的规范,示例如下: https://developers.google.com/maps/documentation/javascript/examples/icon-simple

即使放大,此方法也会以像素为单位进行缩放,而不是实际不同的长/纬度。

答案 10 :(得分:0)

尝试这种方式,按事件获取div。

marker.addListener("click", markerClicked);

function markerClicked(event) {
    // here you can get the marker div by event.currentTarget
}
相关问题