2010-04-20 48 views
20

取代Google Maps API的默认信息窗口,我将使用其他jQuery工具提示插件而不是标记。所以我需要得到标记的DIV和它的像素位置。如何访问Google Maps API v3标记的DIV及其像素位置?

但不能得到它,因为没有特定标记的id或类。只有我可以从标记对象和未记录的pixelBounds对象访问地图canvas div。

  1. 如何访问标记的DIV?
  2. 我在哪里可以得到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 + ")"); 
}); 
+0

这个问题不应该被标记为接受吗?看起来你的问题已经解决了。 – 2012-05-04 04:17:15

+0

@jeff - 您正在编辑超过2年的问题,不断将它们撞到活动列表的顶部。代码已经正确格式化,使颜色漂亮是一个小的改变,并不是必要的。 – LittleBobbyTables 2012-08-06 17:50:36

+8

@LittleBobbyTables - 此问题已被浏览近19,000次。我认为有人会最终找到有用的语法突出显示。 – jeff 2012-08-06 17:53:24

回答

45

我真的不明白你为什么要获得标记的特定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阅读。

+0

除了工具提示之外,我想用jQuery为标记添加动画,这就是为什么我需要访问标记的DIV。现在我知道我无法通过地图API v3访问它,并需要使用OverlayView重新实现标记类。 :( – 2010-04-23 07:44:32

+0

有没有人有体面的反向功能? – 2014-01-30 13:24:52

+0

@AnkitAggarwal不幸的是我目前的工作不涉及谷歌地图的工作。这个答案正是我在一些项目中自己开发的,但除此之外,我没有太多的经验地图 – MBO 2014-03-13 22:27:57

1

雷内的答案只给你“世界坐标”(即coords独立的缩放级别和视口)。然而,MBO的答案看起来不错,所以这就是你应该接受和投票的人(我不能像我刚刚注册的那样),因为否则这个解决方案很容易被忽略。

至于“更简单”的版本,您可以使用MapCanvasProjection中的方法代替,但这意味着您必须制作自己的覆盖图。一个例子见here。 :P

9
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

如果只有这个工作,这将是非常棒的。 'overlay.getProjection()'返回'undefined'。 – designermonkey 2011-07-14 11:12:07

+2

overlay.getProjection仅在地图加载后才初始化

为了规避并初始化它,我有一个侦听器调用使用它的函数。我会将代码添加到我的评论顶部。 – Flarex 2011-07-15 16:17:11

+0

非常感谢您为我更新!我已经使用了事件监听器,所以我会尽快实现它! – designermonkey 2011-07-26 15:57:16

1

MapCanvasProjection的fromLatLngToContainerPixel()可能是作者的后。它会给你相对于地图容器的像素偏移量。我做了一些实验并找到了“最简单”的工作解决方案。 (我希望谷歌使这个功能更容易访问!)

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

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) 
); 
+0

这应该是接近顶端,这是国际风格地图的一个非常重要的特征。这个片段最终纠正了我所有的定位问题。 – KoldBane 2016-06-25 19:43:11

1

那么,如果你必须访问DIV,这里有一些代码。请注意,这只适用于标准标记(20x34px),并且会找到所有标记。你可能想要改进这种黑客来满足你的需求...

请注意!这是一个有HACK

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 

    } 
    } 
} 
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 
} 

正如你看到的,越低,变量映射不在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> 
0

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

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

对于许多情况下复杂的数学计算和更改接受的答案中的引脚位置可能是适当的。

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

adjusting the pin offset in photoshop

下面是添加自定义图钉图像规范,举例: https://developers.google.com/maps/documentation/javascript/examples/icon-simple

这种方法肯定会扩展为以像素为单位,而不是实际的不同经度/纬度,甚至当你的偏移放大。

相关问题