[ACCEPTED]-How to call fromLatLngToDivPixel in Google Maps API V3?-projection

Accepted answer
Score: 37

Look at http://qfox.nl/notes/116

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

Ugly indeed. Much easier in v2 - another 1 flaw of google api v3!

Score: 33

I think the easiest way is to ignore Google's 13 desire to make our life harder by removing 12 and hiding useful functions instead of adding 11 new ones, and just to write your own methods 10 that do the same thing.

Here's a version 9 of a function somebody posted somewhere 8 else (I can't find it right now), that worked 7 for me:

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

Now you can call it any time and 6 any where you want. I especially needed 5 it for custom context menus, and it does 4 it's job perfectly.

EDIT: I also wrote a reverse 3 function, fromPixelToLatLng that does exactly the opposite. It 2 is simply based on the first one, with some 1 math applied:

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);
}
Score: 21

I wasn't satisfied with the answers here. So 15 I did some experiments and found the "simplest" working 14 solution, which is close to Ralph's answer, but 13 hopefully more understandable. (I wish Google 12 makes this feature more accessible!)

First 11 you declare a subclass of OverlayView somewhere like 10 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(){};

Then somewhere else in your code where you instantiate 9 the map, you also instantiate this OverlayView 8 and set its map, like 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);

Then, whenever 7 you need to use fromLatLngToContainerPixel, you just do this:

canvasProjectionOverlay.getProjection().fromLatLngToContainerPixel(myLatLng);

Note 6 that because the MapCanvasProjection object 5 will only be available once draw() is called, which 4 is sometime before the map's idle, I suggest 3 creating a boolean "mapInitialized" flag, set 2 it to true on the first map idle callback. And 1 then do what you need to do only after that.

Score: 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

Score: 9

To get a MapCanvasProjection you could derive 6 a class from OverlayView and call the getProjection() method 5 which returns a MapCanvasProjection type

onAdd(), draw() and 4 onRemove() must be implemented to derive 3 from 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';
};

then when you're creating 2 your map

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

For V2 you should be able to call fromLatLngToDivPixel 1 from your GMap2 instance

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

More Related questions