views:

159

answers:

3

The Google Maps API for a Polygon does not offer a drag method.

What would be an efficient way of implementing such a feature (i.e., sufficiently optimised so that it would not kill a four year old laptop)?

Thank you!

A: 

You could have markers for each point on the polygon, these markers could have drag and at the end of each drag, the polygon could be redrawn.

You could also have a marker in the center of the polygon representing the polygon as a whole, when you move that marker, every marker could be moved by the same amount to maintain the shape.

paullb
@paul: Thank you. I have markers for the points of the polygon. I was looking for a way to drag the polygon without having to use another marker: it is a better user experience if they can simply drag any part of the polygon and have the markers on the points move accordingly.
Dave Jarvis
Can you add click/drag listeners etc on the GMap itself and do the calculation if the click was inside the polyon or not?
paullb
@paul: Possibly. I was thinking about trapping the click and mouse move events. My concern is that I would be emulating a "drag" event and that would wreak all kinds of wrong.
Dave Jarvis
+2  A: 

I found the Google Maps V2 Polygon Implementation to be very limiting for the needs I have had and solved it by creating a custom overlay. My group is currently stuck on IE6 so I have yet to migrate over to Google Maps V3 - but taking a quick look at the API shows that you could probably do a similar thing that I did in V2 with V3.

Essentially the idea is:

  1. Create a Custom Overlay
  2. Populate it with your own SVG/VML Polygons and attach a drag event to this custom polygon object

Custom Overlays:

Here is some information to get you started on making your own custom overlay:

http://code.google.com/apis/maps/documentation/javascript/overlays.html#CustomOverlays


Creating your own "Dragable" Polygon Object:

Once you get that down you'll want to add your own polygons to the custom overlay instead of using GPolygons. I went through the painful process of learning SVG/VML and writing a library to bridge SVG/VML together - you could do that, but I would recommend starting by trying to use another library such as Raphaël.

http://raphaeljs.com/

Using Raphaël will save you a whole lot of time trying to figure out how to get cross-browser Vector Graphic (Polygon) functionality - and best of all it supports drag events already, here is an example from their library:

http://raphaeljs.com/graffle.html

Once you have a custom overlay and you are able to throw some Raphaël objects onto it the last step is to translate the coordinates you want from a Lat/Lng value to a Pixel value. This is available in the MapCanvasProjection of V3:

http://code.google.com/apis/maps/documentation/javascript/reference.html#MapCanvasProjection

You can use fromLatLngToDivPixel to figure out what the actual pixel values are for the points on your Raphael polygon, draw it, then add it to the overlay with a drag event.

John
As an afterthought - I found that my Polygon objects performed much faster than GPolygon objects in V2 - I do not know how they perform in V3, but I found that creating your own Polygons directly with SVG/VML results in a much lighter object that you have more control over directly. I am not sure if Google is using SVG/VML or Canvas now to draw their Polygons - it has changed a couple times throughout versions.
John
@John: Thank you for the wealth of information. It will be interesting to see how well the polygons perform in V3. If you're curious to see how I want to use them, check out: http://www.whitemagicsoftware.com/software/climate/guru.shtml (I want to drag the quadrilateral around.)
Dave Jarvis
+1  A: 

Okay - so after seeing the website you are trying to implement I started to feel like Raphael may not be necessary because it is a pretty heavy JS Library - and if you are only trying to draw a rectangle polygon I thought, why not just do it with a single lightweight DIV instead?

However I think the Raphael solution would still hold water for many other cases - so I think I'll just post another possible answer.

Here is a working example I threw together:

http://www.johnmick.net/drag-div-v3/

Feel free to take a look at the source:

http://www.johnmick.net/drag-div-v3/js/main.js

Essentially we do the following

  1. Create the Custom Overlay
  2. Create the draggable div polygon and, using jQuery UI, make it draggable
  3. Tie an event that listens to when the dragging has stopped that updates the LatLng position of the rectangle
  4. Add the object to the Custom Overlay
  5. Implement the draw function to redraw the rectangle during zooms and pans

Currently I am only storing one LatLng value for the Rectangle (being the top left corner) - you could easily extend this example to store all 4 points of the rectangle and have the shape dynamically resize itself on zooms. You may want to do that, otherwise as users zoom out they will get a climate report for a larger and larger area.

John
@John: Definitely an interesting idea. There are a few things to know: (1) each of the four markers can be dragged to make any contiguously enclosed 4-sided figure, such as a V-shape; and (2) eventually there will be more than four markers (click to add/remove markers).
Dave Jarvis
@John: Thanks again, by the way.
Dave Jarvis
@Dave: Ah now that sounds like a interesting thing to solve - for doing complex polygon shapes you may be best off learning SVG/VML - it's really not so bad, if not a little tedious - that way you could keep track of however many points and draw whatever shape in any size you want. Oh and you are very welcome! Making my own improved GPolygon objects was a huge dilemma for me a couple years ago so I am really happy to pass on anything I learned to help somebody else out.
John
@John: Another SO user helped me out by crafting the code that implements an algorithm to prevent the polygon from getting tied in knots. It's extremely useful. Once I find some time, I plan to open up the code. If you drag one of the markers between two others, you'll see what I mean. I have not seen any other site that treats polygons this way.
Dave Jarvis