Bing Maps Concepts
(formerly Virtual Earth)
Mike Garza   
VEMaps@garzilla.net   

   
Concept: Draggable Polygon - Bing Maps v7

I have gotten a couple of requests to take some of the Bing Maps 6.x examples and port them over to the Bing Maps AJAX control v7. This example is based off of Moveable Polygon example that I put together previous, now moved over to Bing Maps v7. Generally speaking, the conversion was not that difficult. Once you identify the corresponding objects, methods and properties in the v7 API, the basic logic still applied.

In the example to the right, a polygon has been added to the map. The necessary events have been wired up so that when you “click” (and hold) on the polygon, you have the ability to drag it to a new location on the map. One you release [the mouse button] the map returns to the normal mode.

The concept and logic is pretty much the same as the Bing Map v6.x example. While dragging, the distance the mouse moves is being applied to the points in the polygon. The one improvement that could be made to this example would be to implement some sort of buffer so that only reasonable amounts of change would be applied to the polygon. Right now, even the smallest amount of [mouse] movement will updated the points in the polygon.

Walk Through:

The initial map is implemented in the typical fashion, so we will not touch on that in this walk through. A polygon is then added to the map. Again, this is done in the typical fashion and there is nothing special about the implementation, so we won’t touch on those details (feel free to view source for more information).

Once the map and the polygon have been initialized, a series of events are wired up to support the dragging process. The implementation is as follows:

    //Wire events for dragging
    Microsoft.Maps.Events.addHandler(MyPolygon, 'mousedown', StartDragHandler);
    Microsoft.Maps.Events.addHandler(map, 'mousemove', DragHandler);
    Microsoft.Maps.Events.addHandler(MyPolygon, 'mouseup', EndDragHandler);
    Microsoft.Maps.Events.addHandler(MyPolygon, 'mouseout', EndDragHandler);
    

In this code, four events are wired up. Three pertain to the polygon (MyPolygon) and the other pertains to the map. The three parmeters to the “addHandler” function are the target object (the object raising the event), the name of the event to be captured and the function to be executed when the event is raised. For example, line two indicates that when the “MyPolygon” object raises the “mousedown” event, the “StartDragHandler” function is executed.

The whole process starts when end user clicks (and holds) on the polygon. This causes the polygon to raise the “mousedown” event and the “StartDragHandler” function is executed. The implementation of that function is as follows:

    //mousedown handler
    function StartDragHandler(e) {
        dragging = true;
        previousLoc = map.tryPixelToLocation(new Microsoft.Maps.Point(e.getX(), e.getY()));
    }
    

When the function is executed an instance of a “MouseEventsArgs” object is passed to the function. That object is assigned to the variable “e”. Next we need an indicator that the map is now in dragging mode, so we set the variable “dragging” to “true”. This variable will be used throughout the entire process to determine what mode the map is in. Lastly we, on line 3, we create a new instance of a Location object that reflects the current location (latitude and longitude) of the mouse cursor on the map.

To build the Location object that represents the mouse location, a new Point object is created using the getX() and getY() properties of the event object “e”. This Point object is then passed to the tryPixelToLocation() method on the “map” object, which converts the Point object to a Location object. This Location object is then assigned to the variable “previousLoc”.

Now that the map is in “drag” mode, as the mouse moves the location of the polygon needs to be updated. For this we are going to rely on the “map” object to raise the “mousemove” event and when it does, the function “DragHandler” will be executed. The implementation of that function is as follows:
    //mousemove handler
    function DragHandler(e) {
        if (dragging) {
            var loc = map.tryPixelToLocation(new Microsoft.Maps.Point(e.getX(), e.getY()));
            var latVariance = 0;
            var longVariance = 0;
            
            //determine variance
            latVariance = loc.latitude - previousLoc.latitude;
            longVariance = loc.longitude - previousLoc.longitude;
            
            previousLoc = loc;
            
            //adjust points in current shape
            var currentPoints = e.target.getLocations();
            for (var i = 0; i < currentPoints.length; i++) {
                currentPoints[i].latitude += latVariance;
                currentPoints[i].longitude += longVariance;
            }
            
            //set new points for polygon
            e.target.setLocations(currentPoints);
            
            e.handled = true;
        }
    }
    

Conceptually the logic here has not changed much from the Bing Maps v6.x example. You can refer to that article for more detailed information. As with the previous function, a “MouseEventsArgs” object is passed into this function and assigned to the variable “e”. Since this function is going to be executed each time the mouse is moved on the map, we only want to execute the underlying logic if the map is in “drag” mode. The variable “dragging” (set during the mousedown event) is tested to see if the map is in dragging mode. If so, the remaining logic for the function is executed.

First a Location object is created that represents the current location of the mouse and that Location object is assigned to the variable “loc”. This process is similar to the process outlined in the StartDragHandler function. Once we have that information, the difference between the starting location (previousLoc) and current location (loc) is captured (lines 9 &10) and assigned to the variables “latVariance” and “longVariance”. The current location (loc) now becomes the startingLocation (previosuLoc) for the next iteration of this event (if called).

Now that we know how much the mouse has moved, that distance needs to be applied to all of the points in the polygon. The getLocations() method in the target object of the passed in MouseEventsArgs object, e, is executed to get an array of Location objects. (Note: the target object is the object that raised the event, in this case the polygon.) The array of Location objects is then assigned to the variable “currentPoints”.

Next we loop through the Location objects in the currentPoints array and adjust the latitude and longitude properties by the variance amount previously determined. Once all of the coordinates have been updated, the polygon can be reset. The newly updated Location object array, currentPoints, is passed to the setLocations() method in the target object of the MouseEventsArgs object, e. This updates the polygon with all the new point information and the polygon is redrawn in its new location.

Since this event is also used by the map to actually move the map, we need to stop the map object from panning the map at the same time we are trying to drag the polygon. This is accomplished by setting the “handled” property of the MouseEventsArgs object, e, to “true”. This effectively cancels the event and prevents any additional logic (map panning) from being excuted.

This process repeats each time the mouse moves, while in dragging mode. To exit dragging mode, the mouse button just needs to be released. When the mouse button is released, the “mouseup” event is fired and the “EndDragHandler” function is executed. The implementation of that function is as follows:

    //mouseup & mouseout handler
    function EndDragHandler(e) {
        dragging = false;
    }
    

This function is clearly simple. It just takes the map out of dragging mode by setting the variable “dragging” to false. One thing to note is that this function actually facilitates two events. It handles the “mouseup” and “mouseout” events from the Polygon object.

Under normal circumstances this function will be executed when the mouse button is released. However, there were instances, in testing, that the mouse slipped off the edge of the polygon when dragging and an exception was raised. Implementing the “mouseout” event was a means of handling that situation.

Wrap-up:

As mentioned, this example is based off of the Moveable Polygon example that was originally written for the Bing Maps v6.x control. The example was migrated to the Bing Maps AJAX Control v7. The basic process for moving the polygon is the same and v7 of the Bing Maps AJAX control has all of the comparable objects to facilitate the process. The end result is that you can now implement a polygon that can [still] be moved to any location on the map.

This is just one approach that can be taken to implement this type of functionality and is intended to illustrate the mechanics behind this concept. Your implementation will vary depending on your specific needs. As always, feedback, comments or questions are welcome. I look forward to hearing from you.

Return to Home Page

©2007-2017, Mike Garza, All Rights Reserved