Complete SDK Example


This example shows a realistic integration path using a class-based pattern that encapsulates the SDK, map, and place state. This is one of many valid approaches — the same flow works equally well with plain functions, React hooks, or framework-specific state management. It combines:
- SDK initialization
- map creation
- place loading
- marker creation
- polygon styling
- route creation
- map fitting
End-to-end example
import {
TextPosition,
initializeSDK,
loadStyles,
type MapVXMap,
type MapVXSDK,
type MVXPlace,
} from "@mapvx/web-js"
loadStyles()
class MapExperience {
private readonly sdk: MapVXSDK
private map?: MapVXMap
private places: MVXPlace[] = []
constructor(private readonly apiKey: string) {
this.sdk = initializeSDK(apiKey, {
lang: "es",
cache: {
persistent: true,
},
})
}
async init(container: HTMLElement, parentPlaceId?: string): Promise<void> {
const center = await this.resolveInitialCenter(parentPlaceId)
this.map = this.sdk.createMap(container, {
center,
zoom: parentPlaceId ? 18 : 16,
parentPlaceId,
onMapReady: () => {
console.log("Map ready")
},
onFloorChange: (floorId) => {
console.log("Floor changed", floorId)
},
})
await this.loadPlaces(parentPlaceId)
this.renderInitialMarkers()
}
private async resolveInitialCenter(parentPlaceId?: string) {
if (parentPlaceId) {
const parentPlace = await this.sdk.getPlaceDetail(parentPlaceId)
return parentPlace.position
}
const places = await this.sdk.getAvailablePlaces()
return places[0]?.position ?? { lat: 4.666918, lng: -74.053065 }
}
private async loadPlaces(parentPlaceId?: string): Promise<void> {
this.places = parentPlaceId
? await this.sdk.getSubPlaces(parentPlaceId)
: await this.sdk.getAvailablePlaces()
}
private renderInitialMarkers(): void {
if (!this.map) return
this.places.slice(0, 3).forEach((place) => {
this.map!.addMarker({
id: `marker-${place.mapvxId}`,
coordinate: place.position,
floorId: place.inFloors?.[0],
text: place.title,
textPosition: TextPosition.bottom,
icon: "/assets/icons/marker-info.svg",
iconProperties: {
width: 36,
height: 36,
},
anchor: "bottom",
})
})
}
async focusPlace(placeId: string): Promise<void> {
if (!this.map) return
const place = await this.sdk.getPlaceDetail(placeId)
this.map.setPlacesAsSelected([place.mapvxId], "#0F766E")
this.map.addBorderToPlaces([place.mapvxId], "#134E4A", 2)
this.map.fitCoordinates([place.position], {
maxZoom: 19,
})
}
async routeBetween(originId: string, destinationId: string): Promise<void> {
if (!this.map) return
const route = await this.map.addRoute({
initialLocation: { id: originId },
finalLocation: { id: destinationId },
preferAccessibleRoute: false,
})
const parentPlaceId = this.places.find((place) => place.mapvxId === destinationId)?.parentId
if (parentPlaceId) {
this.map.fitRouteByPlace(route, parentPlaceId, {
padding: {
top: 80,
right: 40,
bottom: 120,
left: 40,
},
})
}
}
destroy(): void {
this.map?.removeAllMarkers()
this.map?.removeAllRoutes()
this.map?.destroyMap()
}
}
const experience = new MapExperience("<YOUR_API_KEY>")
experience.init(document.getElementById("map") as HTMLElement, "<OPTIONAL_PARENT_PLACE_ID>")What this example intentionally leaves out
- custom HTML markers: see HTML Markers
- animated routes: see Route Animation
- custom geolocation: see Geolocation Override
- remote configuration and CSS customization: see Remote Configuration
Last updated on