HERE Indoor Maps provides a wealth of hyperlocal information about indoor spaces including building geometry and points of interest, spanning across multiple floors. If you are a building owner and are interested in leveraging HERE Indoor Maps with the Maps API for Javascript, contact us at venues.support@here.com.
Setting up HERE Indoor Maps
The following is required to use HERE Indoor Maps in the Maps API:
The app credentials must have access to the requested Indoor Map.
Include the HERE Indoor Maps module script in the <head> section of the HTML page:
To create the map, make sure to follow the Quick Start guide.
Loading the Indoor Map
Use the platform object to get the instance of H.venues.Service to load your Indoor Maps and create a H.venues.Provider object to control of the loaded Indoor Maps:
// Get instance of the Indoor Maps serviceconst venuesService = platform.getVenuesService({ apikey:'API KEY'});// Indoor Maps provider interacts with a tile layer to visualize and control the Indoor Mapconst venuesProvider =newH.venues.Provider();// Indoor Maps service provides a loadVenue method
venuesService.loadVenue(VENUE_ID).then((venue)=>{// add Indoor Map to the venues provider
venuesProvider.addVenue(venue);
venuesProvider.setActiveVenue(venue);// create a tile layer for the Indoor Maps provider
map.addLayer(newH.map.layer.TileLayer(venuesProvider));// center the map on the Indoor Map
map.setCenter(venue.getCenter());
map.setZoom(15);});
Example Indoor Map
Figure 1.
The example above shows an Indoor Map on the map.
Changing levels
The Provider facilitates the control of the Indoor Map. To get information about the current level or change the level:
// Get active Indoor Mapconst venue = venuesProvider.getActiveVenue();// get current level index
venue.getActiveLevelIndex();// and change level
venue.setActiveLevelIndex(1);
Search
The H.venues.Venue object provides a search functionality through the search method. The search string is not case sensitive and also looks for close matches:
// Get the active Indoor Mapconst venue = venuesProvider.getActiveVenue();// Search for bathrooms
venue.search('Bathroom');
Indoor Maps user interface
Default UI elements control Drawings and Levels using H.venues.ui.DrawingControl and H.venues.ui.LevelControl:
// Get the active Indoor Mapconst venue = venuesProvider.getActiveVenue();// Create the level controlconst levelControl =newH.venues.ui.LevelControl(venue);
ui.addControl('level-control', levelControl);// Create the drawing control:const drawingControl =newH.venues.ui.DrawingControl(venue);
ui.addControl('drawing-control', drawingControl);
Indoor Map objects
The Indoor Map data is encapsulated in a hierarchy of objects. These objects perform as other MapObjects and are represented by the following classes:
H.venues.Venue
H.venues.Drawing
H.venues.Level
H.venues.Geometry
The root is Venue, which contains one or more Drawings, which contains one or more Levels. And the Level object holds the relevant collection Geometry objects.
The raw data associated with each object is accessible through the getData() method.
The classes extend H.map.Feature.
Indoor routing
The classes H.venues.Service and H.venues.Route enable calculating a route between points and visualizing the route on the map in a few simple steps.
Calculating a route
To calculate a route to or from a building, it is required to provide a point as well as the venue id and the level id for the point. Let's replace the origin and destination in the example below with one point inside the Indoor Map and one outside:
// Calculate the routeconst result =await venuesService.calculateRoute({// Provide latitude and longitude for an origin point outside a building
origin:{
coordinates:[52.15,5.38]},// Provide latitude, longitude and venue information for a destination point inside a building:{
coordinates:[VENUE_LATITUDE,VENUE_LONGITUDE],
venueId:VENUE_ID,
levelId:LEVEL_ID},
transportMode:'pedestrian',});
Visualizing the route
The resulting route data can be visualized using the class H.venues.Route:
// Create a route object using the data for the routeconst route =newH.venues.Route(result.routes[0]);// Get Indoor Map objects representing indoor segmentsconst indoorObjects = route.getIndoorObjects();// Link map objects with venue levels for automatic visibility updates and add to the mapfor(let venueId in indoorObjects){for(let levelIndex in indoorObjects[venueId]){const venue = venuesProvider.getVenue(venueId);const objectGroup = indoorObjects[venueId][levelIndex];// Add objects to the map
map.addObject(objectGroup);// Link to an Indoor Map level
venue.setMapObjects(objectGroup.getObjects(), levelIndex);}}// Get map objects representing outdoor segmentsconst outdoorObjects = route.getOutdoorObjects();// Add objects to the map
map.addObject(outdoorObjects);
Customizing the route style
Using the H.venues.Route's optional styleCallback parameter supports customization of the the route style. The styling requires three parameters:
The index of the current route section
All route sections
Segment object type
Based on the given input, the callback returns the style object (H.map.Icon or H.map.SpatialStyle) or undefined. In the latter case, the map object won't be created.
// Define line and marker styles for segmentsconst indoorRouteSegmentStyle =newH.map.SpatialStyle({strokeColor:'#1ab4bf', lineWidth:3});const outdoorRouteSegmentStyle =newH.map.SpatialStyle({strokeColor:'#1ab4bf', lineWidth:3});const exampleSvgIcon =newH.map.Icon('<svg width="18" height="18" '+'xmlns="http://www.w3.org/2000/svg">'+'<circle cx="8" cy="8" r="8" '+'fill="#1ab4bf" stroke="white" stroke-width="2" />'+'</svg>');const routeStartIcon = exampleSvgIcon;const routeEndIcon = exampleSvgIcon;const sectionStartIcon = exampleSvgIcon;const sectionEndIcon = exampleSvgIcon;// Define attribution logic based on segments and objects of the routeconststyleCallback=(index, sections, objectType)=>{if(objectType ===H.venues.Route.ObjectType.SEGMENT_START_MARKER){if(index ===0){return routeStartIcon;}return sectionStartIcon;}elseif(objectType ===H.venues.Route.ObjectType.SEGMENT_FINISH_MARKER){if(sections.length ===1|| index === sections.length -1){return routeEndIcon;}return sectionEndIcon;}return sections[index].departure.place.type ==='indoor'?
indoorRouteSegmentStyle : outdoorRouteSegmentStyle;};// Create route by specifying the styleCallbackconst route =newH.venues.Route(result.routes[0], styleCallback);// Add route to the map using the previous steps...
Figure 2.
The example above shows an example route within an Indoor Map.