Skip to main content

Custom UX

Smplr.js provides a few options that help you customize the floor plan experience to your requirements. We're regularly adding new options, so reach out and share what you'd like to do with it.

Adapting the look & feel and experience

Render options

To customize how the viewer renders the space, you can pass in a number of options to the rendering engine. Below are the options currently exposed. Render options should be passed through startViewer as described right below, or updated dynamically as described further.

interface RenderOptions {
backgroundColor?: string;
grounds?: {
render?: boolean;
};
walls?: {
render?: boolean;
alpha?: number;
maxHeightCm?: number;
showStructuralWalls?: boolean;
};
objects?: boolean;
annotations?: boolean;
compass?: boolean;
skybox?: boolean;
floorplan?: {
render?: boolean;
alpha?: number;
elevationInCm?: number;
};
}
  • backgroundColor - optional - lets you change the background color used by the viewer. You can pass any valid CSS color string, such as 'pink' or '#81b1b3'. We advise to set the same background color on the container element to keep the load screen consistent. As for the preview image, you can change its background color to match in the editor: go to the 'Services' tab and click 'Create preview image'.
  • grounds.render - optional - set this value to control whether the grounds are rendered or not. Default value: true
  • walls.render - optional - set this value to control whether the walls are rendered or not. Note that with render: false, doors and windows will not be rendered either. You can use alpha: 0 instead if you want to render doors and windows but not walls. Default value: true
  • walls.alpha - optional - is a number between 0 and 1 setting the opacity of the walls, 0 being transparent and 1 opaque. Default value: 1
  • walls.maxHeightCm - optional - will cap the rendering of walls to the height provided in centimeter, ignoring the actual height of walls.
  • walls.showStructuralWalls - optional - set this value to control whether the structural walls (if any) are rendered or not. This also removes the controls from the viewer. Default value: unset (use button control)
  • objects - optional - set this value to control whether the furniture and objects (if any) are rendered or not. Default value: true
  • annotations - optional - set this value to control whether the annotations (if any) are rendered or not. This also removes the show/hide annotations button from the viewer. Default value: unset (use button control)
  • compass - optional - set this value to control whether the compass (if any) is rendered or not. This also removes the show/hide compass button from the viewer. Default value: unset (use button control)
  • skybox - optional - set this value to control whether the skybox is rendered or not. Default value: false
  • floorplan.render - optional - set this value to control whether the floor plan image (if any) is rendered or not. Note that for multi-storey spaces, all levels will have their floor plan image rendered. Default value: false
  • floorplan.alpha - optional - is a number between 0 and 1 setting the opacity of the floor plan image, 0 being transparent and 1 opaque. Default value: 0.5
  • floorplan.elevationInCm - optional - is a number in centimeter setting the elevation from the ground at which the floor plan image is rendered. Default value: 2

Get in touch if you have thoughts on other parameters we could expose to better support your needs.

Viewer options

You can set a number of options when starting the viewer. They are listed below in addition to the basic viewer controls documented in the overview page.

space.startViewer({
// ...basicControls
renderOptions?: RenderOptions,
topShownLevel?: number,
includeLevels?: number[],
cameraPlacement?: {
alpha: number,
beta: number,
radius: number,
target: {
x: number,
y: number,
z: number
}
},
disableCameraControls?: boolean,
disableCameraRotation?: boolean,
hideNavigationButtons?: boolean
}) => void
  • ...basicControls - refer to the overview page.
  • renderOptions - optional - is described above in Render options. Default value: {}.
  • topShownLevel - optional - lets you set the initial level the viewer should navigate to. See details in Navigating levels.
  • includeLevels - optional - list of zero-based indices of the levels to render. See includeLevels for details.
  • cameraPlacement - optional - set the initial position and direction of the camera. See camera controls for more details.
  • disableCameraControls - optional - set this to true so the camera placement cannot be changed by the user. This disables mouse, touch and keyboard inputs as well as removes the zoom control buttons. Default value: false
  • disableCameraRotation - optional - set this to true to force a top view of the scene. It essentially gets the interactivity to match the 2D mode, but in 3D mode. Default value: false
  • hideNavigationButtons - optional - set this to true if you want the user to control the camera but want to remove the navigation buttons. Mouse, touch and keyboard inputs will work while the buttons are hidden. Default value: false

Viewer controls

Update render options dynamically

Render options are described in details in Render options. They can be set when the viewer starts, but if you need to update them dynamically, you should use the method below:

space.updateRenderOptions(options: RenderOptions) => void
  • options is an object of the RenderOptions interface, which is deeply merged with the current options used by the viewer. To "unset" an optional value, you can pass undefined explicitely.

This is the programmatic equivalent to pressing the level buttons in the bottom-left controls:

space.showUpToLevel(levelIndex: number) => void
  • levelIndex - zero-based index of the top level you want to see. For example, setting levelIndex to 2 is equivalent to pressing the L3 button.

You can also reset the viewer back to showing all the levels with:

space.showAllLevels() => void

Control which levels are included in the render

When you have a multi-storey building but would like to only render a few floors, you can call this method:

space.includeLevels(levelIndices: number[]) => void
  • levelIndices - list of zero-based indices of the levels to render. See Navigating levels to learn more about levelIndex or level indices.

You can also reset the viewer back to rendering all levels with:

space.includeAllLevels() => void

Camera controls

Get the camera placement

space.startViewer lets you define the initial placement of the camera using the cameraPlacement option. You would typically embed the viewer and have an interface to retrieve one or more placement(s) to be stored in your database. You can then load any placement object from your database to set the initial value. The camera placement can be retrieved with the following function:

space.getCameraPlacement() => ({
alpha: number,
beta: number,
radius: number,
target: {
x: number,
y: number,
z: number
}
})

The "placement" is a Javascript object that includes the position and direction of the camera. It is defined as an orbit position (alpha, beta, radius) around a target point which the camera points towards.

  • alpha is the angle given in radians of the camera's position in the horizontal plane. -Math.PI/2 corresponds to position of the 2D editor.
  • beta is the angle given in radians of the camera's position in the vertical plane. 0 corresponds to a top down view, while Math.PI/2 corresponds to a view from the ground.
  • radius is the distance in meters between the camera and the target point.
  • target is an object providing the (x,y,z) coordinates of the target point, which is the point where the camera is pointed towards.

Set the camera placement

You can move the camera to a specific position and have it target a specific point as well by calling the following function:

space.setCameraPlacement({
alpha?: number | (currentValue: number) => number,
beta?: number | (currentValue: number) => number,
radius?: number | (currentValue: number) => number,
target?: {
x?: number | (currentValue: number) => number,
y?: number | (currentValue: number) => number,
z?: number | (currentValue: number) => number
},
animate?: boolean,
animationDuration?: number
}) => void
  • placement parameters (see description above) can be provided as the new desired value, or a function taking the current value as sole argument and returning the desired value. All parameters are optional and the ones that are not provided will keep their current value.
  • animate - optional - should be set to false to jump to the new placement and true to animate the camera to the new placement. Default value: false
  • animationDuration - optional - defines the duration of the camera animation in seconds and should be used with animate set to true. Default value: 0.6

See the controlled camera example to see this used in action.

Center the camera on the space

This is the programmatic equivalent to pressing the center camera button in the bottom-left controls:

space.centerCamera() => void

Zoom in/out

This is the programmatic equivalent to pressing the zoom buttons in the bottom-left controls:

space.zoomIn() => void
space.zoomOut() => void

Reacting to events from the viewer

You can add event listeners on the viewer to react to interactions happenning in it. The list of event types that can be observed is limited at the moment, and we'll be adding more based on users needs and demand.

Event types available

The event types currently available are as follow:

  • CameraStartedMoving - emitted once when the camera starts moving (rotate, pan, zoom)
  • CameraStoppedMoving - emitted once when the camera stops moving

Event types can be specified as string value or via the EventType Typescript enum. Both methods are type checked if you use Typescript.

Add a listener

space.addEventListener(event: EventType | string, handler: () => void): number
  • event - one of the event type listed above.
  • handler - a function that will be called each time the event of the provided type is emitted.

The function returns a unique listenerId that can be used to remove the listener.

Remove a listener

space.removeEventListener(listenerId: number): void
  • listenerId - unique id of the listener to remove, it is provided as return value when calling addEventListener.

Clear listeners for a given event type

space.clearEventListeners(event: EventType | string): void
  • event - one of the event type listed above.

Clear all listeners

space.clearAllEventListeners(): void