Skip to content

Commit ba6165b

Browse files
Update to indoor map examples, added more scenarios
1 parent fa4c662 commit ba6165b

File tree

2 files changed

+210
-16
lines changed

2 files changed

+210
-16
lines changed

indoor-map/demo.html

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,16 @@ <h1>Show an Indoor Map</h1>
5656
<h3>Code</h3>
5757
<p>
5858
The example shows loading the Indoor Map using <code>H.venues.Service</code> and renders the indoor map using an instance of <code>H.venues.Provider</code>.<br>
59-
The example also shows the usage of the indoor map related UI controls to change levels and buildings using <code>H.venues.ui.LevelControl</code> and <code>H.venues.ui.DrawingControl</code> respectively.
59+
The example also shows:
60+
<ul>
61+
<li>the usage of the indoor map related UI controls to change levels and buildings using <code>H.venues.ui.LevelControl</code> and <code>H.venues.ui.DrawingControl</code> respectively.</li>
62+
<li>disabling the base map while loading a indoor map</li>
63+
<li>switching to an indoor map level other than the default</li>
64+
<li>searching geometries in an indoor map and highlighting them</li>
65+
<li>displaying an info-bubble on click of a geometry</li>
66+
<li>restricting the map movement within the indoor map bounds</li>
67+
<li>rotating the map</li>
68+
</ul>
6069
</p>
6170
<script type="text/javascript" src='demo.js'></script>
6271
</body>

indoor-map/demo.js

Lines changed: 200 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,98 @@
1+
/**
2+
* Example for Indoor Map for JSMapsApi.
3+
*/
4+
5+
// Replace with your HERE platform app api key
6+
const yourApikey = 'ZKBUeAgkzH4JWhg93AA7cIE_kZotbMGhVI0_UYC0COY';
7+
8+
// Replace with your indoor map platform collection hrn
9+
const indoorMapHrn = 'hrn:here:data::org651595200:indoormap-ed6d5667-cfe0-4748-bbf5-88b00e7e3b21-collection';
10+
11+
// Replace with the venue id for your map. This example works for maps:
12+
// 7348 - Zurich Airport
13+
// 27158 - Tiefgarage Riem Arcaden APCOA Parking garage
14+
// 22766 - Mall of Berlin
15+
const venueId = '7348';
16+
17+
// The value of the drawing id varies as per the venue being loaded. Replace with appropriate value.
18+
const drawingId = 7880;
19+
20+
// Set to false if base map is not needed to be displayed.
21+
const showBaseMap = true;
22+
23+
// Value of Level index to set other than the default
24+
const levelIndex = 1;
25+
26+
// Set to true if map needs to be rotated
27+
const rotateMap = false;
28+
29+
// Set to true if serched geometries need to be highlighted
30+
const searchHighlightGeometries = false;
31+
32+
// Set to true to show info bubble with gemetry information on click of geometry
33+
const enableInfoBubble = false;
34+
var infoBubble;
35+
36+
// Set to true to restrict a moveable indoor map to the bounds of the venue
37+
const restrictMapWithinMapBounds = false;
38+
139
/**
240
* Load and add indoor data on the map.
341
*
442
* @param {H.Map} map A HERE Map instance
543
*/
644
function addVenueToMap(map) {
745
// Get an instance of the Indoor Maps service using a valid apikey for Indoor Maps
8-
const venuesService = platform.getVenuesService({ apikey: 'ZKBUeAgkzH4JWhg93AA7cIE_kZotbMGhVI0_UYC0COY',
9-
hrn: 'hrn:here:data::org651595200:indoormap-ed6d5667-cfe0-4748-bbf5-88b00e7e3b21-collection' }, 2);
10-
11-
// Indoor Maps provider interacts with a tile layer to visualize and control the Indoor Map
12-
const venuesProvider = new H.venues.Provider();
46+
const venuesService = platform.getVenuesService({ apikey: yourApikey, hrn: indoorMapHrn }, 2);
1347

1448
// Indoor Maps service provides a loadVenue method
15-
// This example works for maps:
16-
// 7348 - Zurich Airport
17-
// 27158 - Tiefgarage Riem Arcaden APCOA Parking garage
18-
// 22766 - Mall of Berlin
19-
venuesService.loadVenue('7348').then((venue) => {
49+
venuesService.loadVenue(venueId).then((venue) => {
2050
// add Indoor Maps data to the Indoor Maps provider
2151
venuesProvider.addVenue(venue);
2252
venuesProvider.setActiveVenue(venue);
2353

2454
// create a tile layer for the Indoor Maps provider
25-
map.addLayer(new H.map.layer.TileLayer(venuesProvider));
55+
const venueLayer = new H.map.layer.TileLayer(venuesProvider);
56+
map.addLayer(venueLayer);
57+
if (!showBaseMap) {
58+
map.setBaseLayer(venueLayer);
59+
}
2660

2761
// Set center of the map view to the center of the venue
2862
map.setCenter(venue.getCenter());
2963

30-
// optionally select a different level
31-
venue.setActiveDrawing(7880);
64+
// Optionally select a different active drawing.
65+
if (venue.getDrawing(drawingId)) {
66+
venue.setActiveDrawing(drawingId);
67+
}
3268

33-
// create a level control
69+
// Optionally set a different active level
70+
if (venue.getLevels().length >= levelIndex) {
71+
venue.setActiveLevelIndex(levelIndex);
72+
}
73+
74+
// Create a level control
3475
const levelControl = new H.venues.ui.LevelControl(venue);
3576
ui.addControl('level-control', levelControl);
3677

37-
// create a drawing control:
78+
// Create a drawing control:
3879
const drawingControl = new H.venues.ui.DrawingControl(venue);
3980
ui.addControl('drawing-control', drawingControl);
81+
82+
// Enable highlighting geometries based on geometry name
83+
if (searchHighlightGeometries) {
84+
highlightGeometries(venue, 'Duty Free Store');
85+
}
86+
87+
// Enable info bubble on tap of geometry
88+
if (enableInfoBubble) {
89+
enableBubbleOnTap();
90+
}
91+
92+
// Enable to restrict map movement within indoor map bounds
93+
if (restrictMapWithinMapBounds) {
94+
restrictMap(map, venue);
95+
}
4096
});
4197
}
4298

@@ -69,5 +125,134 @@ var behavior = new H.mapevents.Behavior(new H.mapevents.MapEvents(map));
69125
// Step 4: create the default UI component, for displaying bubbles
70126
var ui = H.ui.UI.createDefault(map, defaultLayers);
71127

128+
// Indoor Maps provider interacts with a tile layer to visualize and control the Indoor Map
129+
const venuesProvider = new H.venues.Provider();
130+
72131
// Step 5: add the Indoor Map
73132
addVenueToMap(map);
133+
134+
// Other helpful steps for indoor maps
135+
136+
// Rotate map
137+
if (rotateMap) {
138+
map.getViewModel().setLookAtData({
139+
tilt: 0,
140+
heading: 90
141+
});
142+
}
143+
144+
/**
145+
* Function to search and highlight geometries
146+
*
147+
* @param {H.venues.Venue} venue
148+
* @param {H.venues.Provider} venuesProvider
149+
* @param {string} geometryForSearch - geometry name to be searched
150+
*/
151+
function highlightGeometries (venue, geometryForSearch) {
152+
const searchGeometries = venue.search(geometryForSearch);
153+
const highlightStyle = {
154+
fillColor: '#FF0000',
155+
outlineColor: '#99cc00',
156+
outlineWidth: 0.2,
157+
};
158+
159+
if (searchGeometries.length > 0) {
160+
venuesProvider.activeVenue.setHighlightedGeometries(true, searchGeometries, highlightStyle);
161+
// venuesProvider.activeVenue.setHighlightedGeometries(false, searchGeometries, highlightStyle); // If you need to remove the highlighting
162+
}
163+
}
164+
165+
/**
166+
* For a given location open an information popup and highlight geometry.
167+
* @param {mapsjs.geo.Point} position tapped on map
168+
* @param {H.venues.Geometry} geometry which was tapped
169+
* @param {boolean} highlight geometry or not
170+
*/
171+
const onGeometryTap = (position, geometry, highlight = true) => {
172+
// Hide existing infoBubble and remove existing highlight
173+
if (infoBubble) {
174+
const currentGeometry = infoBubble.getData();
175+
if (currentGeometry) venuesProvider.getActiveVenue().setHighlightedGeometries(false, [currentGeometry]);
176+
ui.removeBubble(infoBubble);
177+
}
178+
179+
infoBubble = new H.ui.InfoBubble(position, {
180+
onStateChange: () => {
181+
// On closing the popup, removing highlight from the geometry
182+
venuesProvider.getActiveVenue().setHighlightedGeometries(false, [infoBubble.getData()]);
183+
},
184+
});
185+
186+
ui.addBubble(infoBubble);
187+
188+
// Then set a new geometry at info bubble
189+
infoBubble.setData(geometry);
190+
191+
if (highlight) {
192+
venuesProvider.getActiveVenue().setHighlightedGeometries(true, [infoBubble.getData()]);
193+
}
194+
195+
const popUpContent = `${geometry.getId()}: ${geometry.getName()} <br>`;
196+
197+
const domElement = document.createElement('div');
198+
domElement.innerHTML = popUpContent;
199+
domElement.setAttribute('style', 'width: max-content;');
200+
201+
infoBubble.setPosition(position);
202+
infoBubble.setContent(domElement);
203+
204+
// if content is available, open the infoBubble
205+
return popUpContent.length > 0 ? infoBubble.open() : infoBubble.close();
206+
};
207+
208+
/**
209+
* This function demonstrates how to add an event listener to the venue
210+
*/
211+
const enableBubbleOnTap = () => {
212+
venuesProvider.addEventListener('tap', (e) => {
213+
const geometry = e.target;
214+
215+
if (geometry) {
216+
const position = map.screenToGeo(e.currentPointer.viewportX, e.currentPointer.viewportY);
217+
setTimeout(() => onGeometryTap(position, geometry, true), 0);
218+
}
219+
});
220+
};
221+
222+
/**
223+
* Restricts a moveable map to a given rectangle.
224+
*
225+
* @param {H.Map} map A HERE Map instance within the application
226+
*/
227+
function restrictMap(map, venue){
228+
229+
var bounds = venue.getBoundingBox(); // to get BBox for the indoor map
230+
231+
map.getViewModel().addEventListener('sync', function() {
232+
var center = map.getCenter();
233+
234+
if (!bounds.containsPoint(center)) {
235+
if (center.lat > bounds.getTop()) {
236+
center.lat = bounds.getTop();
237+
} else if (center.lat < bounds.getBottom()) {
238+
center.lat = bounds.getBottom();
239+
}
240+
if (center.lng < bounds.getLeft()) {
241+
center.lng = bounds.getLeft();
242+
} else if (center.lng > bounds.getRight()) {
243+
center.lng = bounds.getRight();
244+
}
245+
map.setCenter(center);
246+
}
247+
});
248+
249+
//Debug code to visualize where your restriction is
250+
map.addObject(new H.map.Rect(bounds, {
251+
style: {
252+
fillColor: 'rgba(55, 85, 170, 0.1)',
253+
strokeColor: 'rgba(55, 85, 170, 0.6)',
254+
lineWidth: 8
255+
}
256+
}
257+
));
258+
}

0 commit comments

Comments
 (0)