Venue Maps in Windows Store Apps (JavaScript)

Within Bing Maps you have the ability to view Venue Maps. Venue Maps are often thought of as maps of indoor structures such as malls and airports; however, venue maps can be opened up to so much more. A few examples of other types of venue maps include: the layout of shopping districts, stadiums, race courses, and universities.

Using Venue Maps in Bing Maps requires loading in the Venue Map module. If you are not familiar with modules in Bing Maps take a look at the blog post on Bing Maps Modules in Windows Store Apps.

In this blog post, we are going to create a simple application that when zoomed in, will load in nearby venues into Bing Maps in your Windows Store App as you pan the map around.

Setting up the project

To set up the project, open Visual Studios 2012 and create a new project. In the window that opens select JavaScript -> Windows Store. Select the Blank App template, and call the application VenueMaps_JS and press OK.

To keep things clean we are going to create a separate JavaScript file for our application. Right click on the js folder and select Add -> New Item. Create a new JavaScript file called VenueMaps.js.

At this point your Solution should look something like this:

 

clip_image001

 

Next, add a reference to the Bing Maps JavaScript library. To do this, right click on the References folder and press Add Reference. Select Windows -> Extensions select Bing Maps for JavaScript. If you do not see this option ensure that you have installed the Bing Maps Windows Store App SDK.

Now we can open up the default.html file and add references to the Bing Maps SDK along with references to the Bing Maps modules API and our JavaScript file. While we are at it, we will also add a div to the body of the page where we want the map control to load. Your default.html file should look like this:

 

<!DOCTYPE html>

<html>

<head>

    <meta charset="utf-8" />

    <title></title>

 

    <!-- WinJS references -->

    <link href="//Microsoft.WinJS.1.0/css/ui-dark.css" rel="stylesheet" />

    <script src="//Microsoft.WinJS.1.0/js/base.js"></script>

    <script src="//Microsoft.WinJS.1.0/js/ui.js"></script>

 

    <!-- VenueMaps_JS references -->

    <link href="/css/default.css" rel="stylesheet" />

    <script src="/js/default.js"></script>

 

    <!-- Bing Maps references -->

    <script type="text/javascript"

            src="ms-appx:///Bing.Maps.JavaScript//js/veapicore.js"></script>

    <script type="text/javascript"

        src="ms-appx:///Bing.Maps.JavaScript//js/veapimodules.js"></script>

 

    <!-- Our Venue Maps JavaScript Code -->

    <script src="/js/VenueMaps.js"></script>

 

    <style type="text/css">

        div {

            color:#000;

        }

    </style>

</head>

<body>

    <div id="myMap"></div>

</body>

</html>

Loading the Bing Maps Control

We will add the functionality to load the Bing Maps control to the VenueMap.js file. To start, we are going to create six global variables called: map, _mapBounds, _zoom, venueFactory, loadedVenues, and loadedVenueIds. Then, we will create a function called GetMap which will load the Bing Maps control for us. When loading the Bing Maps control we will also turn on the breadcrumb. The breadcrumb allows us to select different floors when viewing a venue. Inside of this function we will load in the Venue Maps module and initialize the venueFactory object. Now we will add a throttled event handler for when the map has finished moving that will get nearby venues. The GetMap function will be loaded after the Microsoft.Maps.Map module has completed loading. Your code should look like this:

 

var map,

    loadedVenues = [],

    loadedVenueIds = [],

    _mapBounds,

    _zoom,

    venueFactory;

 

function GetMap() {

    var mapOptions =

    {

        credentials: "YOUR_BING_MAPS_KEY",

        zoom: 2,

        showBreadcrumb : true

    };

 

    map = new Microsoft.Maps.Map(document.getElementById("myMap"), mapOptions);

 

    //Load the venue map module

    Microsoft.Maps.loadModule('Microsoft.Maps.VenueMaps', {

        callback: function () {

            venueFactory = new Microsoft.Maps.VenueMaps.VenueMapFactory(map);

 

            //Use a throttled event to reduce the number of unwanted events being fired.

            Microsoft.Maps.Events.addThrottledHandler(map, 'viewchangeend', GetNearbyVenues, 250);

        }

    });

}

 

//Initialization logic for loading the map control

(function () {

    function initialize() {

        Microsoft.Maps.loadModule('Microsoft.Maps.Map', { callback: GetMap });

    }

 

    document.addEventListener("DOMContentLoaded", initialize, false);

})();

Adding the Application Logic

When the veiwchangeend event handler is fired, it will trigger a function called GetNearbyVenues. This function will first loop through all loaded venues and dispose those that are out of view or all of them if the zoom level is less than 14. When disposing a venue we will also delete the stored venue id in the loadedVenueIds array. If the zoom level is greater or equal to 14 we will do a search for all venues that are within 4000 meters of the center of the map.

 

function GetNearbyVenues() {

    _mapBounds = map.getBounds();

  _zoom = map.getZoom();

 

    //Dispose a venue if it is outside of the map view or if the zoom level is too high

    var venuesInView = [], venue;

 

    for (var i = 0; i < loadedVenues.length; i++) {

        venue = loadedVenues[i];

 

        if (_zoom < 14 || !_mapBounds.contains(venue.center)) {

            delete loadedVenueIds[venue.id];

            venue.dispose();

        } else {

            venuesInView.push(venue);

        }

    }

 

    loadedVenues = venuesInView;

 

    if (_zoom >= 14) {

        // Search for venues that are within 4km of the center of the map

        venueFactory.getNearbyVenues({ map: map, location: map.getCenter(), radius: 4000, callback: DisplayNearbyVenues });

    }

}

 

When the search for nearby venues completes, a function called DisplayNearbyVenues will be fired. This function will loop through the venues that are returned and check if the venue has been loaded by checking the loadedVenueIds array. If the venue hasn’t been loaded we will create the venue and check to see if it is in the current map view and add both the venue and the venue id to the loadVenues and loadedVenueIds arrays. If it was loaded, we will then show it on the map. If it hasn't, we will dispose it. We will also attach a close event handler to the venue so that we can properly dispose it and remove any reference from our arrays.

 

function DisplayNearbyVenues(venues) {

  if (venues) {

        //Load new venues that are in view

        for (var i = 0; i < venues.length; i++) {

            if (loadedVenueIds[venues[i].metadata.MapId] == undefined) {

                venueFactory.create({

                    venueMapId: venues[i].metadata.MapId,

                    success: function (v) {

                        if (_mapBounds.contains(v.center)) {

 

                            //Handle close event of venue

                            Microsoft.Maps.Events.addHandler(v, 'close', function (e) {

                                delete loadedVenueIds[v.id];

                               

                                //Remove venue from loadedVenues array

                                for (var j = 0; j < loadedVenues.length; j++) {

                                    if (loadedVenues[j].id == v.id) {

                                loadedVenues.splice(j ,ji+1);

                                        break;

                                    }

                                }

 

                                v.dispose();

                            });

 

                            loadedVenues.push(v);

                            loadedVenueIds[v.id] = true;

                            v.show();

                        } else {

                            v.dispose();

                        }

                    }

                });

            }

        }

    }

}

Running the App

At this point we have created all the functionality needed for nearby venues to be loaded as we navigate the map. If we run the app, zoom in and pan around in an area with the venue maps we should see the footprint of the venue load on the map. If you click on a venue footprint the map will zoom in on that venue and show the inside of the venue map. Here is a screen shot of the app with the venue map of Alder Hey Children’s Hospital located in Liverpool, UK.

 

Win8_Venue

- Ricky Brundritt, EMEA Bing Maps Technology Solution Professional