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

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

但不能得到它,因为没有特定标记的id或类。 只有我可以从标记对象和未logging的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 + ")"); }); 

我真的不明白你为什么要获得标记的特定div? 如果你想显示工具提示,那么你所需要的只是标记锚点的像素位置(以及有关标记大小和锚点位置的知识),而不是div元素。 当google.maps端发生事件时,您可以随时触发开启和closures工具提示。

为了获得给定标记的锚点的像素位置,您可以使用以下代码:

 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您可以从地图的左上angular计算特定标记锚点的偏移量(您可以从map.getDiv() div)获取它的位置。 为什么它像这样工作(还是有更好的方法?)你可以阅读谷歌地图覆盖文件 。

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

您现在可以通过px和py来访问像素坐标

后续添加发表评论:

叠加投影的失败是,直到它的地图canvas完成加载它不被初始化。 我有下面的监听器,将强制任何方法我需要触发时,地图完成加载。

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

同时,我使用以下检查来避免在绘制之前发生任何错误。

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

使用MBO代码时要记住的一件事情是:当地图切片重复时, map.getBounds().getSouthWest()返回“-180”,与地图位置无关。 在这种情况下,我使用的备用方法是计算到中心的像素距离而不是左上angular,因为在任何情况下, 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) ); 

任何人仍然在寻找这个答案,看看这里: http : //code.google.com/p/google-maps-utility-library-v3/wiki/Libraries之间的一些其他有用的谷歌地图的东西有RichMarker它允许您可以将您select的DOM元素添加为可拖动标记。 只需添加class / id来处理jQuery。

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

对于“更简单”的版本,您可以使用MapCanvasProjection中的方法,但是这意味着您必须创build自己的叠加层。 看这里的例子。 :P

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

首先,你可以像这样声明一个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之前的某个时间,所以我build议创build一个布尔型“mapInitialized”标志,并在第一个地图idlecallback中将其设置为true。 然后在那之后做你需要做的事情。

那么,如果你必须访问DIV,这里是一些代码。 注意,这只能使用标准标记(20x34px),它会find所有的标记。 你可能想要改进这个黑客来满足你的需求…

谨防! 这是一个黑客

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

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

正如你所看到的,更低的variables映射前面没有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> 

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

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

在许多情况下,复杂的math计算和更改接受的答案中的销位置可能是适当的。

为了我的特殊用途,我创build了一个透明的PNG,canvas比我需要的图标大得多。 然后,我只是尝试在透明背景中移动引脚,并将新图像应用到地图上。

调整在Photoshop中的引脚偏移量

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

这种方法肯定会缩放为像素的偏移量,而不是实际的不同长/纬度,即使放大时也是如此。