Multi Floor View & Stacked Maps
Mappedin JS version 6 is currently in a release candidate state while Mappedin perfects new features and APIs. Open the v6 release notes to view the latest changes.
Using Mappedin JS with your own map requires a Pro license. Try a demo map for free or refer to the Pricing page for more information.
Multi Floor View
Multi Floor View is a feature that displays all floors in a building stacked vertically below the active floor, allowing users to see the building's vertical structure and navigate between floors. The active floor is fully rendered while lower floors appear as semi-transparent footprints.
Multi Floor View is enabled by default. It can be controlled using the multiFloorView
option when initializing the map view as shown in the code sample below. In this example, the map view is initialized with the initialFloor
set to m_952cd353abcb1a13
, which is ID of the 10th floor of the building. Other Multi Floor View options are defined in TMultiFloorViewOptions and include the ability to set the gap between floors as well as whether the camera should move when the active floor changes.
Code Sample
const mapView = await show3dMap(
document.getElementById("mappedin-map") as HTMLDivElement,
mapData,
{
initialFloor: "m_952cd353abcb1a13",
multiFloorView: {
enabled: true, // Default is true.
floorGap: 10, //Default is 10.
updateCameraElevationOnFloorChange: true, //Default is true.
},
}
);
It is possible to set multiple floors to be visible at once, which can be useful for overlaying data within the building, such as the locations of security cameras or other assets. This can be done by setting the visible property to true for each floor that should be shown, using TFloorUpdateState as shown in the code sample below.
// Show the 6th floor as well.
const floor = mapData.getByType("floor").find((f) => f.elevation === 6);
mapView.updateState(floor, {
geometry: { visible: true },
});
When displaying multiple floors, by default content such as labels, markers, paths and images are only visible on the active floor. These can be displayed on additional visible floors by enabling them for the floor using TFloorUpdateState as shown below.
mapView.updateState(floor, {
visible: true,
altitude: 0,
geometry: {
visible: true,
},
images: { enabled: true },
labels: { enabled: true },
markers: { enabled: true },
paths: { enabled: true },
});
Interactive Example
This CodeSandbox below shows a simple example of MultiFloor View where maps of the 6th and 9th floors are visible.
Stacked Maps
Stacked Maps consist of individual layers that represent different floors of a multi-story building. These layers are conceptually or digitally stacked to create a complete view of the structure, allowing users to visualize, navigate, and interact with multiple floors in an integrated way.
Stacked Maps can be enabled by setting the visibility of floors that should appear in the stack to true
and altering their altitude defined in TFloorUpdateState, so that each floor is raised above the previous floor. There are two ways to modify the visibility and altitude of a floor:
- MapView.animateState() gradually moves the floor to the new altitude over a specified duration of time.
- MapView.updateState() instantly snaps the floor to the new altitude.
Alternative visualization methods can also be created by using variations of this technique. For example, an app may wish to only show the top and bottom floors of a building, or only show the floors that are currently accessible to the user by setting the visibility of the floors to true
or false
based on the apps requirements.
When displaying multiple floors, by default content such as labels, markers, paths and images are only visible on the active floor. These can be displayed on additional visible floors by enabling them for the floor using TFloorUpdateState as shown below.
mapView.updateState(floor, {
images: { enabled: true },
labels: { enabled: true },
markers: { enabled: true },
paths: { enabled: true },
});
Code Sample
The following code sample shows how to enable Stacked Maps by setting the visibility of all floors to true
and altering their altitude. Two methods are provided to expand and collapse the stacked maps view. Each method provides the option to use animateState
or updateState
to alter the altitude of the floors. It also puts the camera in elevation mode when expanding the floors and returns to default mode when collapsing the floors, which makes it easier for the user to move up and down to see the floors.
import { Floor, TCameraAnimationOptions } from "@mappedin/mappedin-js";
export type TExpandOptions = TCameraAnimationOptions & {
distanceBetweenFloors?: number;
cameraPanMode?: "default" | "elevation";
};
export function expandFloors(
mapView: any,
mapData: any,
options?: TExpandOptions
) {
const distanceBetweenFloors = options?.distanceBetweenFloors ?? 10;
mapView.Camera.setPanMode(options?.cameraPanMode ?? "elevation");
mapData.getByType("floor").forEach((floor: Floor) => {
const newAltitude: number = floor.elevation * distanceBetweenFloors;
const isCurrentFloor = floor.id === mapView.currentFloor.id;
const currentState = mapView.getState(floor);
if (currentState) {
if (!currentState.visible || !currentState.geometry.visible) {
mapView.updateState(floor, {
visible: true,
altitude: 0,
geometry: {
visible: true,
opacity: isCurrentFloor ? 1.0 : 0.0,
},
});
}
}
if (options?.duration ?? 0 > 0) {
mapView.animateState(
floor,
{
altitude: newAltitude,
geometry: {
opacity: 1.0,
},
},
{
duration: options?.duration ?? 0,
easing: options?.easing ?? "ease-in-out",
}
);
} else {
mapView.updateState(floor, {
altitude: newAltitude,
visible: true,
geometry: {
visible: true,
opacity: 1.0,
},
});
}
});
}
export function collapseFloors(
mapView: any,
mapData: any,
options?: TCameraAnimationOptions
) {
mapView.Camera.setPanMode("default");
mapData.getByType("floor").forEach((floor: any) => {
const isCurrentFloor = floor.id === mapView.currentFloor.id;
if (options?.duration ?? 0 > 0) {
mapView.animateState(
floor,
{
altitude: 0,
geometry: {
opacity: isCurrentFloor ? 1.0 : 0.0,
},
},
{
duration: options?.duration ?? 0,
easing: options?.easing ?? "ease-in-out",
}
);
setTimeout(() => {
mapView.updateState(floor, {
visible: isCurrentFloor ? true : false,
altitude: 0,
geometry: {
visible: isCurrentFloor ? true : false,
opacity: isCurrentFloor ? 1.0 : 0.0,
},
});
}, options?.duration ?? 0);
} else {
mapView.updateState(floor, {
altitude: 0,
visible: isCurrentFloor ? true : false,
geometry: {
visible: isCurrentFloor ? true : false,
opacity: 1.0,
},
});
}
});
}
Interactive Example
This sample code is implemented in the CodeSandbox below.