While google maps v2 had a simple fromLatLngToContainerPixel(latlng, z) on every projection (and the other way around as well), v3 seems to be lacking a bit in its api. While this certainly isn't the only thing the api lacks, it's at least something that was solved quite quickly with the help of the google maps group.
So in v2 you could do
map.getProjection().fromLatLngToContainerPixel(latlng, 4)
and you'd get the proper point according to given zoom index. v3 almost has that method, but only on the
MapCanvasProjection
object and only without a zoom parameter. Suck.
So here is your
fromLatLngToPixel
and
fromPixelToLatLng
, in gmaps v3 style. I found it in
this post (
last reply, I don't know how to link to that directly... UI fail?).
/**
* @param {google.maps.Map} map
* @param {google.maps.LatLng} latlng
* @param {int} z
* @return {google.maps.Point}
*/
var latlngToPoint = function(map, latlng, z){
var normalizedPoint = map.getProjection().fromLatLngToPoint(latlng); // returns x,y normalized to 0~255
var scale = Math.pow(2, z);
var pixelCoordinate = new google.maps.Point(normalizedPoint.x * scale, normalizedPoint.y * scale);
return pixelCoordinate;
};
/**
* @param {google.maps.Map} map
* @param {google.maps.Point} point
* @param {int} z
* @return {google.maps.LatLng}
*/
var pointToLatlng = function(map, point, z){
var scale = Math.pow(2, z);
var normalizedPoint = new google.maps.Point(point.x / scale, point.y / scale);
var latlng = map.getProjection().fromPointToLatLng(normalizedPoint);
return latlng;
};
It works quite simple actually. But it would probably help if the docs would have explained this one slightly better.
Some interesting facts to help explaining this function:
map.getProjection().fromLatLngToPoint
returns normalized values, between 0 and 255
- each tile in google maps is 256 pixels wide and high
- when zooming in google maps, the deeper layer is twice the size of the layer above
So "my"
latlngToPoint
function uses these facts. First it asks where the
latlng
would be on zoom level 0 (this is one tile of 256x256 pixels). You can't get to zoom level 0 by normal means (but you can somewhat clearly see that level 1 consists of four tiles). We get a very high precision floating number back, between 0 and 255.
Next we take the zoom level. Each level increases the size by two fold so to get the size of the "world" at zoom level z, we need to double it z times. That's what
Math.pow(2,z)
does. The last step is actually multiplying the normalized coordinate with the zoom factor and voila, there's the point in our world at zoom level z.
Of course,
pointToLatlng
is simply the inverse of that.
Please note that there is
another method (
again, last reply) of doing this. Sort of. It involves creating a new
MapCanvasProjection
and using
fromLatLngToContainerPixel
from that. Like..
overlay = new google.maps.OverlayView();
overlay.draw = function() {};
overlay.setMap(map);
var point = overlay.getProjection().fromLatLngToContainerPixel(latLng);
I can only say uuuuugeleeeeey. Thanks. Please use the two functions I described first :)
Hope it helps you :)