Custom marker: How to calculate coordinate of the icon anchor in V3?

774 views
Skip to first unread message

magicrat75

unread,
Feb 7, 2011, 9:53:33 AM2/7/11
to google-map...@googlegroups.com
Hi everyone

I've got a problem with a custom marker icon anchor in V3. In my site I have to draw some custom markers and depending on some parameters move a bit (some pixels) the icon image from its real coordinate. I do this using the anchor property of the icon. (For those of you who are curious, I have to move a bit the image because we don't want to draw it over the exact position as there may be some info there which the user may need).
Then, on clicking over the marker, I open an Infowindow and to better indicate the actual position of the marker, I draw a line from the icon anchor position to the real coordinate.

My problem is while trying to calculate the coordinate for the anchor. In API v2 I used map.fromLatLngToDivPixel, but in API 3 I hadn't been able to make it work (I'm using projection, see the code I use on the link I provide).

Has any one had to do something similar? Or can anyone give me a clue as to how to get the coordinate for the anchor or any other way to move a bit the icon from its coordinate and then draw a line from the icon to the coordinate???

I've built a sample of my app that can be found here:
http://www.lariereta.com/testCustomMarker/testCustomMarker.html

Some info on the code and site:
- The problem with the coordinate of the anchor position is on the function "getIconLine".
- The possible movements are hardcoded (in pixels) at the beginning of the code (under 'Possible icon movements').
- I've commented the code and tried to make it easy, as I perfectly understand that solving this kind of problems from someone else maps isn't easy at all.
- The link site is not the real one (this domain is from a friend of mine) and the link is not for the real site either (the code is quite big and has lots of things which aren't related with this problem). I've just done this sample so that I could provide a link to the map and to make it easier for anyone to try to give me a hint on how to solve the problem. But in this sample I do exactly the same thing that in the site I'm developing and I have exactly the same problem with the line coordinates. I'm sure if I can sort out this problem in this sample code, I will fix it on the site I'm developing.

Any hint will be gratefully accepted.
Thanks in advance.
D.

Martin Matysiak

unread,
Feb 7, 2011, 11:59:05 AM2/7/11
to google-map...@googlegroups.com
I'm not absolutely sure if I've understood your problem, so here's what I think you want to do:

You have an marker-icon that is shifted some pixels (!) away from the actual location you want to point at. When the user clicks on the marker, a line from your anchor to the actual location shall be drawn. Is this correct?

If this would be the case, I have implemented the following method:

/*
* Calculates the Latitude/Longitude per
* Pixel ratio based on the given zoom.
*
* If you want to speed up things, you might
* replace the formula by an array of constant
* LatLng values, as the ratio isn't depending
* on any factors but the map's scaling. If
* This should change in the future, you would have
* to adjust the formula either way.
*
* @param zoom The zoom value for which you want
* to know the conversion ratio from
* pixel to LatLng
*/
function getLatLngPerPixel(zoom) {
var lng = 360 / (256 * (Math.pow(2,zoom))); //256 is the Map Width (px) on zoom = 0
var lat = 2 * lng / Math.PI;

return new google.maps.LatLng(lat, lng);
}
This method gives you the "size" of a pixel in Latitude/Longitude coordinates for a specific map zoom (by the way, you could also fill this method with a static array containing the precalculated values for each zoom). Now if you want to draw a line from your location to the anchor, just get the conversion ratio, take your location as point A of the line, then calculate point B of the line by multiplying your x/y values with the corresponding conversion ratio and adding this to the coordinates of your point A.

bratliff

unread,
Feb 7, 2011, 12:41:03 PM2/7/11
to Google Maps JavaScript API v3
Unfortunately, LngToX & XToLng are linear but LatToY & YToLat are non
linear. Using a constant multiplier for the vertical component will
not work. It is the reason Google has to chop flat images into
horizontal slices to force a Euclidian projection to look like a
Mercator projection. At very deep zoom levels, you may not notice it.

Several different versions of the conversion functions are floating
around. See:

http://www.polylib.us/adjust.js

magicrat75

unread,
Feb 8, 2011, 1:49:13 AM2/8/11
to google-map...@googlegroups.com
Hi Martin

Yes, that's exactly what I want to do. I'll try your method and see how it comes out. Thanks for your help!!!

I understand moving the icon from its actual position and drawing a line to toe actual coordinate may seem weird, but:
- we want the user to know the exact point where the marker is placed
- we do no want to place the whole icon in it (may have more markers very close by and some other information that the user needs).
As a result, displacing the icon and drawing the line seemed the best idea. I'm open to suggestions though.

D.

magicrat75

unread,
Feb 8, 2011, 1:57:54 AM2/8/11
to google-map...@googlegroups.com
Thanks for the tip bratliff.

I'll start by implementing the basic method that Martin suggested and then I'll try to improve and correct it using your examples.

As an extra info:
- I'll have to work in zoom levels 8 to 12 (both included)
- The pixels that I move the icon are not much (between 4 and 38, depending on the location of the icon)
- And something that may be important and I forgot to mention before: the line doesn't have to go to the anchor exactly. It has to point to the exact coordinate (which I have), but on the icon side the line just have to finish "under the icon". I just asked for the anchor coordinate because that's how I did this in v2. Any point under the icon (so that the line goes from the icon to the real coordinate) will be good enough.

I'll post the solution I implemented once I'm done and satisfied with it.

Thanks to both of you.
D.

magicrat75

unread,
Feb 8, 2011, 11:22:38 AM2/8/11
to google-map...@googlegroups.com
Hi

I've been able to solve my problem thanks to Martin function. As Martin said, what I've done is calculate the lat/lng for the 5 zoom levels I need and to get the proper coordinate I simply multiply this value by some pixels (depending on the movement/icon size). Of course, if anyone wants to try something like this, the zooms and movements may have to be different from mine, but I guess this could be easily adapted.

I've updated the link to my sample page (I'll keep the link active for as long as I can). The link is the same than before:
http://www.lariereta.com/testCustomMarker/testCustomMarker.html

To better test the site, I've done two more changes to the sample:
- I've limited the zoom levels to the ones I need.
- As I have eight possible movements, I've drawn 8 markers, one for each of the movements, so that I could test it thoroughly.

Thanks to everyone.
D.



bratliff

unread,
Feb 8, 2011, 11:41:12 AM2/8/11
to Google Maps JavaScript API v3
Multiplying by a constant is fine for the X component but not for the
Y component. X is linear. Y is non-linear.

Martin Matysiak

unread,
Feb 8, 2011, 11:44:04 AM2/8/11
to google-map...@googlegroups.com
Great to hear that it works, I noticed a small bug, though: when you click on a marker and then change the zoom, the line does not get updated and it appears too long or too short. So maybe you should listen for the "zoom changed" event and update the lines if this happens :-)

And thanks to bratliff for pointing out the fact that the latitude isn't linear, didn't know that. However in my use case the linear approximation seems to work out quite well, as I don't need highly accurate conversions.

magicrat75

unread,
Feb 8, 2011, 1:56:26 PM2/8/11
to Google Maps JavaScript API v3
Hi

Thanks for telling me about the problem when zooming with the marker
open Martin. I'll try to sort it out.

Bratliff, even though it is not linear, as happens to Martin, the line
is good enough for my purposes. What I effectively need is the line to
go from the marker actual coordinat to "somewhere under the icon" so
that the icon is clearly marked. Taking into account the little pixels
and the small range of zooms I allow, this works well enough for me.

D.

nikolajp

unread,
Feb 9, 2011, 3:51:09 AM2/9/11
to Google Maps JavaScript API v3
Why not use the world coordinates instead?
They do not have the issue of the coordinate system being non-linear
with Latitude.

I use "fromLatLngToPoint(latLng:LatLng, point?:Point)".
You get a float coordinate between 0-256.
When you have caculated the displacement in world coordinates you
simply convert back to lng/lat whenplacing it.

.nikolaj
Reply all
Reply to author
Forward
0 new messages