Examples

Basic example

The most basic way of using the Mazemap JS API is to just display a map with the default options.

Use the Mazemap JS API in your webpage by including the mazemap.js and mazemap.css files in the <head> of your webpage:

<link rel="stylesheet" href="https://api.mazemap.com/js/v1.2.5/mazemap.min.css">
<script type='text/javascript' src='https://api.mazemap.com/js/v1.2.5/mazemap.min.js'></script>

Add a container in the <body>:

<div id='mazemap-container'></div>

And initialize that container using Maze.map() in javascript.

<script>
var map = Maze.map('mazemap-container', {});
</script>

The default behaviour is to display a map to the extents of all campuses. Zooming in into a campus will activate it and display its buildings.

See this example stand-alone.


Displaying a set of campuses

The campuses option on the Maze.map() constructor allows viewing a set of campuses other than the default:

<script>
var map = Maze.map('mazemap-container', { campuses: 'ntnu' });
</script>

See this example stand-alone.


Controlling the visible area

Use the Leaflet-compatible setView() method to center the map in a geographical point. Once a campus has been loaded, the floor can be controlled with getZLevel() and setZLevel():

<script>
var map = Maze.map('mazemap-container', {});
map.setView([63.41, 10.41], 12);

setTimeout(function(){
    map.setZLevel(3);
}, 5000);
</script>

See this example stand-alone.


Loading just one campus

To show just one campus, first disable the automatic campus loader with an initialization option:

var map = Maze.map('mazemap-container', { campusloader: false });

Then, fetch a campus instance from Maze.Instancer. This is a Promise which resolves to an instance of Maze.Campus, which is a Leaflet layer. The way to put it together is:

Maze.Instancer.getCampus(1).then( function (campus) {
    map.fitBounds(campus.getBounds());
    campus.addTo(map);
});

The reason why Maze.Instancer.getCampus() returns a Promise is because this operation is asynchronous: the Mazemap JS API contacts the Mazemap servers to know the geometry and details of the campus, and this network operation takes time.

The code above will just add the campus to the map but, by default, campuses do now show buildings in them. To do that, call setActive() on a campus instance. This will trigger a network operation to fetch building information from Mazemap's servers so, once again, this is a asynchronous operation:

Maze.Instancer.getCampus(1).then( function (campus) {
    map.fitBounds(campus.getBounds());
    campus.addTo(map).setActive().then( function() {
        // The buildings are now loaded
    });
});

When activating a campus, it's usually a good idea to show the z-level control and jump to a z-level that exists (by default, the map's z-level is zero):

Maze.Instancer.getCampus(1).then( function (campus) {
    map.fitBounds(campus.getBounds());
    campus.addTo(map).setActive().then( function() {
        map.setZLevel(1);
        map.getZLevelControl().show();
    });
});

See this example stand-alone.


Showing custom POIs

You can create custom markers using Maze.marker and Maze.icon, which work very much like their Leaflet counterparts.

The Mazemap JS API includes Leaflet.Icon.Glyph and the Material design icons webfont, allowing for hundreds of different kinds of markers.

Check the API documentation for more information about the Mazemap-specific zLevel and offZOpacity options.

var marker = Maze.marker([63.41638, 10.40939], {
    icon: Maze.icon.bubble({
        color: 'teal',
        glyph: 'phone',
        glyphColor: 'teal'
    }),
    zLevel: 3,
    offZOpacity: 0.6
});

var marker2 = Maze.marker([63.41572, 10.41082], {
    icon: Maze.icon.chub({
        color: 'red',
        glyph: 'ambulance'
    })
});

marker.addTo(map);
marker2.addTo(map);

map.fitBounds(Maze.latLngBounds(marker.getLatLng(), marker2.getLatLng()));

See this example stand-alone.


Showing custom POI Pop-ups

You can easily add custom popups to your markers using Maze.popup, just like Leaflet Popups.

var marker = Maze.marker([63.43298, 10.40748], {
    icon: Maze.icon.chub({ ... }),    // Add options for your marker icon, e.g. colour or glyph
    zLevel: 4,
    offZOpacity: 0.6
}).addTo(map);

var popup = Maze.popup().setContent('<p><strong>Hello world!</strong><br />I am a printer, and I am located <i>exactly</i> at this indoor location!</p>');

marker.bindPopup(popup); //Bind the popup to the specific marker

Maze.Instancer.getCampus(47).then(function(campus){
    map.fitBounds( campus.getBounds() );
    campus.addTo(map).setActive().then( function(c) {
        map.setZLevel(4);
        map.getZLevelControl().show();

        marker.openPopup(); //For convenience, we want to auto-show this popup
    });
});

See this example stand-alone.


Searching for nearest POIs

It is useful to know what POI is nearest to a given location, for example when the user clicks the map. Such POIs can be fetched with Maze.Instancer.getPoiAt:

map.on('click', function(ev) {
    Maze.Instancer.getPoiAt(ev.latlng, map.getZLevel()).then(function(marker) {
        if (marker) {
            marker.bindPopup(marker.properties.name).addTo(map).openPopup();
        } else {
            map.openPopup('No POI here', ev.latlng);
        }
    });
});

For custom POIs, the raw POI data can be fetched with Maze.Data.getPoiAt, so the marker can be instantiated with custom logic.

The following example adds a bit of extra logic to make sure only one POI is visible at any time:

See this example stand-alone.


Showing POI categories

The easiest way to show all POIs from a POI category is to call addPoiCategory() and removePoiCategory() in an instance of Maze.Campus once it's been loaded:

Maze.Instancer.getCampus(1).then( function (campus) {
    map.fitBounds(campus.getBounds());
    campus.addTo(map).setActive().then( function() {
        map.setZLevel(1);
        map.getZLevelControl().show();

        campus.addPoiCategory(27);    // 27 = bus stops
    });
});

See this example stand-alone.

If you need finer control over the POIs, you can also call Maze.Instancer.getPoisByCategoryAndCampusId(categoryId, campusId), which will return a set of Maze.Markers, modify them as needed, and display those which you need to display.

The POI categories available for a given campus can be fetched with Maze.Data.getPoiCategoryIdsByCampusId(campusId), so a list can be made:

See this example stand-alone.


Performing searches

Searches can be performed by calling Maze.Search.search(searchTerm, searchOptions).

Be aware that this method returns raw GeoJSON, not Leaflet-compatible layers. How to display these results (in the map, in a list, etc) is up to the developer.

Maze.Search.search('Hangaren', {
    resultsMax: 10,
    campusId: 1,
    searchForPois: true,
    searchForBuildings: false,
    searchForPoiCategories: false,
    searchForCampuses: false,
}).then( function(results) {
    console.log(results);
});

Route finding

Route finding (finding the shortest path from a starting point to a destination point) is done via Maze.Route.getFeatureGroupRoute() and Maze.Route.getGeoJsonRoute().

These methods are analogous, except that one returns a Leaflet-compatible FeatureGroup and the other a GeoJSON data structure. The FeatureGroup includes fully-symbolized lines and icons for the elevators and stairs.

var startLatLng = [63.41804344188158, 10.40383815765381];
var endLatLng = [63.41821147332781, 10.40382206439972];

Maze.marker(startLatLng, {
    zLevel: 3,
    offZOpacity: 0.4,
    icon: Maze.icon.chub({ color: 'green', glyph: 'human' })
}).addTo(map);
Maze.marker(endLatLng,   {
    zLevel: 3,
    offZOpacity: 0.4,
    icon: Maze.icon.chub({ color: 'red', glyph: 'walk' })
}).addTo(map);


Maze.Route.getFeatureGroupRoute(   // Can be replaced with Maze.Route.getGeoJsonRoute(
    startLatLng, 3,
    endLatLng, 3,
    {
        connectToStart: true,
        connectToEnd: true,
//         avoidStairs: true
    }
).then(function(featGroup){
    featGroup.addTo(map);
    map.fitBounds(featGroup.getBounds());
    map.setZLevel(3);
});

See this example stand-alone.


IoT Asset Tracking

Given that you know the location of physical objects, you can easily make map markers that visualize the assets in near realtime. One way of doing this is to have a web server that continuously keeps track of the asset locations, and then the map part is fairly easy.

This example shows how asset tracking at a hospital can be visualized, using custom icons for the various assets, and the ability to turn layers on/off and clicking markers to see the relevant information.

The update speed of the markers is mainly limited by the actual rate of updates on the backend server side.

See this example stand-alone.

In this example, we are simulating a backend server response by having static .json files for the 'realtime data'. The format of the inputdata is not that important, but it's easier if it comes in GeoJSON format.

    // Example of a single asset feature coming from the server
    {
        "type": "FeatureCollection",
        "features": [
            {
                "type": "Feature",
                "properties": {
                    // These properties are arbitrary and can contain useful data that you can show in the maps
                    "zLevel": 1,
                    "type": "ivpump",
                    "name": "IV Pump #1"
                },
                "geometry": { "type": "Point", "coordinates": [ 10.387313067913057, 63.4201089600874 ] }
            }
        ]
    }
    // Defining a map data layer is very easy with one line of code
    var realtimeDataLayerWheelchairs = Maze.geoJSON({"type": "FeatureCollection", "features": []}).addTo(map);

    // Now data can be added to this layer as such

    realtimeDataLayerWheelchairs.clearLayers(); // Optionally clear existing data points in the layer
    realtimeDataLayerWheelchairs.addData( ... ); // Add GeoJSON formatted data to the layer
    // Easy to get external data updates using the Fetch API (https://developer.mozilla.org/en/docs/Web/API/Fetch_API)

    // Do polling of external data every 5 seconds
    setInterval(function(){
        fetch('https://example.domain.com/data/wheelchairs-realtime.json')
        .then(function(response) {
          return response.json();
        })
        .then(function(geoJson){
            // Update the map data layers
            realtimeDataLayerWheelchairs.clearLayers();
            realtimeDataLayerWheelchairs.addData(geoJson)
            });
    }, 5000);

Polling GeoJSON data every few seconds is probably the easiest method to implement, but the JS API gives you the flexibility to use other techniques such as websockets or server-side event streams. These techniques can provide data deduplication and faster update times but require that the server keeping track of the assets is able to provide updates in the form of websockets or event streams.

Questions? Need help to set-up?

Don't hesitate to contact us with any questions or problems you might have. Do you need a demo using your own asset tracking data? Let us help you get started!

Contact us


Using plugins

The MazeMap JS API is compatible with many map plugins.

We have made an example of using a plugin to visualize a heatmap on top of floor plans.

See examples of how 3rd party map plugins can add even more value to the MazeMap JS API.

See example of plugin usage