2010-04-20 46 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

這種方法肯定會擴展爲以像素爲單位,而不是實際的不同經度/緯度,甚至當你的偏移放大。

相關問題