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

   
Beginning Location: Ending Location:
Lat: 00.0000 Lng: 00.0000 Lat: 00.0000 Lng: 00.0000
Hold down control key & [left] click and drag on the map to draw the selection box.
Concept: Selection Box

In this example, we will implement a “selection box” on the map. There may a scenario where you need to select a range of shapes (push pins) on the map to execute some business process. Rather than select each individual push pin, it would be ideal to draw a selection box on the map to capture all of the push pins with in the bounds of that selected area.

In the example to the right, functionality has been added to allow a selection box to be drawn on the map. The process of drawing the selection box is as follows. Hold down the control key on the keyboard. With the left mouse button, click on the starting location for the selection box and keep the mouse button pressed. While holding down the left mouse button, drag the mouse to the desired end location. While you are dragging the mouse cursor, the selection box will be dynamically drawn on the screen. Once you reach the desired end point, release the left mouse button to complete the selection. In this example, to change the selection box, repeat the previous process.

It should be apparent that there is currently nothing on the map to select. This is intentional. This example deals with the selection box itself. There will be a follow up example that contains some items that can be selected. I wanted to touch on the mechanics of the selection box first.

You’ll notice on the top of the map, there are labels that indicate the boundaries of the current selection box. This will come into play when we add items on the map to be selected, which will be covered in the follow up example.

Walk Through:

The selection box implemented in this example is really nothing more than a polygon or VEShape obect. As the user drags the mouse across the map, the polygon is re-factored and repainted on the map.

The map, itself is created in the typical fashion. We won’t go into that process in this article, but feel free to view the source code for this page for more information. As you’ve probably guessed, since the mouse is involved, we need to wire up some events for this process. This is accomplished as follows:
    // Attach the event handlers to the mouse 
    map.AttachEvent("onmousedown", MouseDownHandler); 
    map.AttachEvent("onmousemove", MouseMoveHandler); 
    map.AttachEvent("onmouseup", MouseUpHandler); 
    
Three events are registered via the AttachEvent() method on the VEMap object, map. These events are “onmousedown”, “onmousemove” and “onmouseup”. When these events are fired they will execute the JavaScript functions “MouseDownHandler”, “MouseMoveHandler” and “MouseUpHandler”, respectively. For more information on event handling, please refer to the Virtual Earth SDK (http://msdn2.microsoft.com/en-us/library/bb412543.aspx ).

MouseDownHandler() – This function will be executed each time a mouse button is pressed. This function will determine if the selecting process should begin and if so, execute the appropriate code. The implementation is as follows:
    function MouseDownHandler(e){ 
        // On mouse down, check to see if the control key is pressed.  If not, do nothing.  If, so start the selection process.
        if(!e.ctrlKey ){ 
            return false;
        } else {
            // enable selecting mode
            selecting = true;

            // set the start points 
            startX = e.mapX; 
            startY = e.mapY; 
            
            StartLatLon = map.PixelToLatLong(new VEPixel(startX, startY));
            
            document.getElementById("BeginLat").innerHTML = StartLatLon.Latitude.toFixed(4);
            document.getElementById("BeginLng").innerHTML = StartLatLon.Longitude.toFixed(4);          

            // disable the VE mouse events 
            return true; 
        }
    }    
    
The selection process should begin only if the user is holding down the control key (not sure what the mac equivalent is, sorry). This can be determined by examining the ctrlKey property of the event object, e, which is a Boolean value. If the control key is being pressed, this property will return true, otherwise false. If true, the process starts, otherwise no code is executed and the function exits.

The selection process begins by setting the value of some variables. First the selection mode is enabled by setting the value of the Boolean variable “selecting” to true. This is an indicator to some of the other functions that the map is in selecting mode. Next the location where the use clicked is captured. The event object, e, has two properties that indicate the current position of the mouse. These properties are mapX and mapY. These values are assigned to the variables startX and startY, respectively. Next the current mouse location is converted into VELatLong obect. This is accomplished by first creating VEPixel object using the startX and startY variables and passing that VEPixel Object to the PixelToLatLong method in the VEMap object, map. This returns a VELatLong object that represents the starting location of the selection box and assigns that object to the variable “StartLatLon”. Lastly (and not germane to the process), two labels on the UI are updated with the latitude and longitude of the starting location.

MouseMoveHandler() – This function will be executed each time the mouse moves. When in selecting mode, this function will have the responsibility of displaying the selection box. The implementation is as follows:
    function MouseMoveHandler(e){ 
        //When moving the mouse, if in "selecting" mode, draw, otherwise do nothing.
        if(!selecting) {
            return false;
        } else {
            // clear select box
            if (selectBox) {map.DeleteShape(selectBox)};

            // set the latest endpoints (opposite side of the selection box) 
            currentX = e.mapX; 
            currentY = e.mapY;
            
            EndLatLon = map.PixelToLatLong(new VEPixel(currentX, currentY));
            
            document.getElementById("EndLat").innerHTML = EndLatLon.Latitude.toFixed(4);
            document.getElementById("EndLng").innerHTML = EndLatLon.Longitude.toFixed(4); 

            // create new selection box (VEShape) from start and end (corners) coordinates
            selectBox = new VEShape( 
                VEShapeType.Polygon, 
                [
                StartLatLon,
                new VELatLong(StartLatLon.Latitude, EndLatLon.Longitude),
                EndLatLon,
                new VELatLong(EndLatLon.Latitude, StartLatLon.Longitude) 
                ]); 
            
            selectBox.HideIcon();
            selectBox.SetLineWidth(2);
            selectBox.SetLineColor(new VEColor(255,0,0, 1.0));
            selectBox.SetFillColor(new VEColor(0, 0, 0, 0));
            selectBox.Primitives[0].symbol.stroke_dashstyle = "DashDot";

            map.AddShape(selectBox); 
        } 
    }    
    
Since this function will be executed each time the mouse moves, we need to test to see if we are in selecting mode. If you recall there is a variable named “selecting”, set in the MouseDownHandler, that determines if we are in selecting mode. If we are in selecting mode, indicated by a “true” value in the variable “selecting”, the code in the function is executed, otherwise the function exits.

Once we are in selecting mode, this function has the responsibility of painting (and repainting) the selection box on the map. This function will use the previously defined starting location, StartLatLon, to build out the selection box. The selection box is nothing more than a styled polygon that is repainted as the mouse moves.

Since we are “repainting” the selection box as the mouse moves, the first thing that is needed is to remove any previous instance of the selection box. The variable “selectBox” represents the VEShape object that is the selection box. If there is a valid object in the selectBox variable (not null), then the selectBox variable/object is passed to the DeleteShape() method in the VEMap object, map. This removes the shape from the map.

Next we capture the current position of the mouse so that the opposite corner of the selection box can be determined. This process is similar to how the starting corner of the selection box was captured in the MouseDownHandler. The mapX and mapY properties of the event object, e, represent the current location of the mouse. These values are assigned to the variables currentX and currentY respectively. Next the current mouse location is converted into a VELatLong object. This is accomplished by first creating a VEPixel object using the currentX and currentY variables. This VEPixel object is passed to the PixelToLatLong() method in the VEMap object, map, which returns a VELatLong object. This VELatLong object is assigned to the variable “EndLatLon”, which, again, represents the opposite the opposite corner of the selection box. Again, labels on the UI are updated to reflect the current end corner of the selection box.

Once the end location or opposite corner of the selection box has been determined, the selection box can be added to the map (repainted). The VELatLong objects StartLatLon and EndLatLon are used to create the VEShape object that represents the selection box. The four corners of the selection box or VEShape polygon, needs to defined to created the selection box. StartLatLon and EndLatLon represent the opposite corners of the selection box, so the other two remaining corners of the selection box need to be defined. Two new VELatLong objects are created using the appropriate Latitude and Longitude properties of the StartLatLon and EndLatLon objects. These two VELatLong object represent the other remaining corners. All four VELatLong objects are put into an array and used to create a new instance of a VEShape polygon object, which is the updated selection box. The updated VEShape object is assigned to the variable selectBox.

Now that the [updated] selection box has been created, the appropriate style attributes can be defined. These include setting the line width, line color, fill color and line style. Also, the icon for this VEShape object is hidden via the HideIcon() method in the VEShape object, selectBox.

Lastly the select box is [re] added to the map. This is done by passing the VEShape object, select box, to the AddShape() method in the VEMap object, map. This process is repeated each time the mouse is moved while in the “selection mode”.

MouseUpHandler() – This function will be executed when the mouse button is released. This function is pretty basic and has the responsibility of disabling the selection mode. The implementation is as follows:
    function MouseUpHandler(e){ 
        // On mouse up, if in selecting mode cancel selecting mode
        if(selecting){ 
            // cancel selecting mode
            selecting = false; 
        } 
    }        
    
While in selection mode, the presumption is that when the mouse button is released, the selection process has been completed. When that occurs, this function will be invoked. If the selection mode has been enabled, determined by a “true” value in the variable “selecting”, the variable “selecting” is set to false, this disabling the selection mode.

Wrap-up:

The previous has been an example of how a selection box could be implemented on a Virtual Earth map. A selection box could aide in the process of selecting multiple push pins at the same time. A follow up article will illustrate the actual selection process itself.

As with any code, there are multiple ways this concept can be implemented (I actually though of another while writing this). Hopefully this example will shed some light on how this can be accomplished.

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