Como chamar fromLatLngToDivPixel na API do Google Maps V3?

Eu sei que esse método existe e está documentado, mas não sei como obter um object MapCanvasProjection.

Olhe para http://qfox.nl/notes/116

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

Feio mesmo. Muito mais fácil em v2 – outra falha do google api v3!

Acho que a maneira mais fácil é ignorar o desejo do Google de tornar nossa vida mais difícil removendo e ocultando funções úteis em vez de adicionar novas funções, e apenas escrever seus próprios methods que fazem a mesma coisa.

Aqui está uma versão de uma function que alguém postou em outro lugar (não consigo encontrá-la agora), que funcionou para mim:

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

Agora você pode ligar a qualquer momento e onde quiser. Eu especialmente precisava de menus de contexto personalizados, e faz o trabalho perfeitamente.

EDIT : Eu também escrevi uma function inversa, fromPixelToLatLng que faz exatamente o oposto. É simplesmente baseado no primeiro, com alguma matemática aplicada:

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

Eu não estava satisfeito com as respostas aqui. Então, fiz alguns experimentos e encontrei a solução de trabalho “mais simples”, que está próxima da resposta de Ralph, mas espero que seja mais compreensível. (Eu desejo que o Google torne esse recurso mais acessível!)

Primeiro você declara uma subclass de OverlayView algum lugar assim:

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

Em seguida, em outro lugar no seu código em que você instancia o mapa, você também instancia este OverlayView e define seu mapa, da seguinte forma:

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

Então, sempre que você precisar usar fromLatLngToContainerPixel , basta fazer isso:

 canvasProjectionOverlay.getProjection().fromLatLngToContainerPixel(myLatLng); 

Observe que, como o object MapCanvasProjection só estará disponível depois que draw() for chamado, o que é algum tempo antes do idle do mapa, sugiro criar um sinalizador booleano “mapInitialized” e defini-lo como true no primeiro retorno de chamada idle mapa. E então faça o que você precisa fazer somente depois disso.

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

Para obter um MapCanvasProjection, você pode derivar uma class do OverlayView e chamar o método getProjection () que retorna um tipo MapCanvasProjection

onAdd (), draw () e onRemove () devem ser implementados para derivar de OverlayView.

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

então quando você está criando seu mapa

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

Para a V2, você deve poder chamar fromLatLngToDivPixel da sua instância do GMap2

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