2009-10-08 19 views

Antwort

28

Blick auf http://qfox.nl/notes/116

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

hässliche Tat. Viel einfacher in v2 - ein weiterer Fehler von Google API v3!

+1

Das funktioniert zunächst perfekt für mich, aber wenn ich die Karte schwenken, werden die Pixelpositionen nicht aktualisiert. Aber wenn ich dann den Zomm-Level ändere, funktioniert es wieder wie erwartet (bis zum nächsten Pan). Fehle ich etwas? –

+8

In Bezug auf den vorherigen Kommentar löste die Verwendung von fromLatLngToContainerPixel anstelle von fromLatLngToDivPixel mein Problem mit Pixelpositionen, die nach dem Verschieben der Karte nicht aktualisiert wurden. –

+0

['google.maps.MapCanvasProjection' Objektspezifikation, die die Methode' fromLatLngToContainerPixel (latLng: LatLng) '' (https://developers.google.com/maps/documentation/javascript/reference?csw=1#MapCanvasProjection) enthält – user664833

9

Um eine MapCanvasProjection erhalten Sie eine Klasse von OverlayView und rufen Sie die getProjection() -Methode, die MapCanvasProjection Typ ableiten könnte

onAdd() zeichnen() und onRemove() muss implementiert werden, von Overlay gibt eine abzuleiten.

function MyOverlay(options) { 
    this.setValues(options); 

    var div = this.div_= document.createElement('div'); 

    div.className = "overlay"; 
}; 

// MyOverlay is derived from google.maps.OverlayView 
MyOverlay.prototype = new google.maps.OverlayView; 

MyOverlay.prototype.onAdd = function() { 

    var pane = this.getPanes().overlayLayer; 
    pane.appendChild(this.div_); 

} 

MyOverlay.prototype.onRemove = function() { 
    this.div_.parentNode.removeChild(this.div_); 
} 

MyOverlay.prototype.draw = function() { 
    var projection = this.getProjection(); 
    var position = projection.fromLatLngToDivPixel(this.getMap().getCenter()); 

    var div = this.div_; 
    div.style.left = position.x + 'px'; 
    div.style.top = position.y + 'px'; 
    div.style.display = 'block'; 
}; 

dann, wenn Sie Ihre Karte

var OverLayMap = new MyOverlay({ map: map }); 

Für V2 sind die Schaffung sollten Sie in der Lage sein fromLatLngToDivPixel von Ihrem GMap2 Instanz anrufen

var centerPoint = map.fromLatLngToDivPixel(map.getCenter()); 
+0

Mischen Sie nicht die API v2 mit v3? –

+0

Diese sind von V3 –

+0

Jetzt mit Ihrer letzten Bearbeitung ist es in Ordnung –

13
var map; 
// Create your map 
MyOverlay.prototype = new google.maps.OverlayView(); 
MyOverlay.prototype.onAdd = function() { } 
MyOverlay.prototype.onRemove = function() { } 
MyOverlay.prototype.draw = function() { } 
function MyOverlay(map) { this.setMap(map); } 
var overlay = new MyOverlay(map); 
var projection = overlay.getProjection(); 
+0

Ich habe diesen Code ausprobiert, und die variable Projektion scheint "undefiniert" zu sein. Irgendeine Idee warum? Vielen Dank! – LaundroMat

+6

Hinweis: (und das hielt mich für eine gute halbe Stunde) - stellen Sie sicher, das Overlay beim Erstellen der Karte zu erstellen, und nicht, wenn Sie die Koordinaten benötigen (via fromLatLngToDivPixel). Wenn Sie dies tun, erhalten Sie Uncaught TypeError: Die Methode 'fromLatLngToDivPixel' von undefined kann nicht aufgerufen werden. Es sieht so aus, als ob Google einige dieser Dinge asynchron ausführt. – AlexeyMK

+0

der Code kann viel vereinfacht werden, siehe meine Antwort – TMS

21

I wasn bin mit den Antworten hier zufrieden. Also habe ich ein paar Experimente gemacht und die "einfachste" Arbeitslösung gefunden, die Ralphs Antwort nahe kommt, aber hoffentlich verständlicher ist. (Ich wünsche Google diese Funktion besser zugänglich macht!)

Zuerst erklären Sie eine Unterklasse von OverlayView irgendwo in etwa so:

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

Dann woanders in Ihrem Code, wo Sie die Karte instanziiert, auch instanziiert diese Overlay und legen Sie seine Karte, etwa so:

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

Dann, wann immer Sie fromLatLngToContainerPixel verwenden müssen, können Sie dies nur tun:

canvasProjectionOverlay.getProjection().fromLatLngToContainerPixel(myLatLng); 

Beachten Sie, dass, weil die MapCanvasProjection Objekt ist nur verfügbar, wenn draw() genannt wird, die irgendwann vor der idle der Karte ist, schlage ich vor, ein boolean „mapInitialized“ Flag erstellen, legen Sie es auf der ersten Karte idle Rückruf zu wahren. Und dann tun Sie, was Sie erst danach tun müssen.

+0

sehr sauber Erklärung – punkish

+0

Dies sollte die akzeptierte Antwort für die Frage sein. sehr klar - danke! – andufo

+0

ernsthaft, das ist genial. – tkone

24

Ich denke, der einfachste Weg besteht darin, Googles Wunsch zu ignorieren, unser Leben zu erschweren, indem nützliche Funktionen entfernt und versteckt werden, anstatt neue hinzuzufügen und nur eigene Methoden zu schreiben, die dasselbe tun.

Hier ist eine Version einer Funktion jemand woanders gebucht (ich kann es jetzt nicht finden), die für mich gearbeitet:

fromLatLngToPixel: function (position) { 
    var scale = Math.pow(2, Map.getZoom()); 
    var proj = Map.getProjection(); 
    var bounds = Map.getBounds(); 

    var nw = proj.fromLatLngToPoint(
    new google.maps.LatLng(
     bounds.getNorthEast().lat(), 
     bounds.getSouthWest().lng() 
    )); 
    var point = proj.fromLatLngToPoint(position); 

    return new google.maps.Point(
    Math.floor((point.x - nw.x) * scale), 
    Math.floor((point.y - nw.y) * scale)); 
}, 

Jetzt können Sie es jederzeit anrufen und jeder, wo Sie wollen. Ich brauchte es vor allem für benutzerdefinierte Kontextmenüs, und es funktioniert perfekt.

EDIT: Ich schrieb auch eine umgekehrte Funktion, fromPixelToLatLng, die genau das Gegenteil der Fall ist. Es basiert einfach auf dem ersten, mit ein paar Mathe angewendet:

fromPixelToLatLng: function (pixel) { 
    var scale = Math.pow(2, Map.getZoom()); 
    var proj = Map.getProjection(); 
    var bounds = Map.getBounds(); 

    var nw = proj.fromLatLngToPoint(
    new google.maps.LatLng(
     bounds.getNorthEast().lat(), 
     bounds.getSouthWest().lng() 
    )); 
    var point = new google.maps.Point(); 

    point.x = pixel.x/scale + nw.x; 
    point.y = pixel.y/scale + nw.y; 

    return proj.fromPointToLatLng(point); 
} 
+0

Funktioniert wie ein Charme. Vielen Dank. –

+0

Danke, das hat bei mir funktioniert. – cyclo

+0

Es ist einfach perfekt. – jalone