diff --git a/docs/api-reference/color/_category_.json b/docs/api-reference/color/_category_.json index 5cae2dd..a0c4c26 100644 --- a/docs/api-reference/color/_category_.json +++ b/docs/api-reference/color/_category_.json @@ -1,4 +1,4 @@ { "label": "Color", - "position": 3 + "position": 4 } diff --git a/docs/api-reference/map/_category_.json b/docs/api-reference/map/_category_.json new file mode 100644 index 0000000..7787194 --- /dev/null +++ b/docs/api-reference/map/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Map", + "position": 2 +} diff --git a/docs/api-reference/map/buildings.md b/docs/api-reference/map/buildings.md new file mode 100644 index 0000000..63ce4b5 --- /dev/null +++ b/docs/api-reference/map/buildings.md @@ -0,0 +1,50 @@ +--- +sidebar_position: 2 +sidebar_label: Buildings +--- + +# Buildings on the map + +One of the main added "layer" the Smplrspace map viewer provides, as compared to just Mapbox is the ability to render 3D spaces from your Smplrspace data, and 3D cities based on OpenStreetMap data in a few lines of code. Here are the functions currently available. + +## Spaces from Smplrspace + +### Add spaces by ID + +To fetch spaces from your Smplrspace account and render them on the map, call the following method. Note that the spaces need to be georeferenced within the platform. + +```ts +map.addSpacesById(spaceIds: string[]) => void +``` + +- `spaceIds` - unique identifiers of the spaces in Smplrspace, something like "fbc5617e-5a27-4138-851e-839446121b2e". + +### Remove spaces by ID + +To remove specific spaces from the map, call this function: + +```ts +map.removeSpacesById(spaceIds: string[]) => void +``` + +- `spaceIds` - unique identifiers of the spaces in Smplrspace, something like "fbc5617e-5a27-4138-851e-839446121b2e". + +### Remove all spaces + +To remove all spaces from the map, call this function: + +```ts +map.removeAllSpaces() => void +``` + +## 3D cities + +### Control OSM layer + +To control whether to render the 3D cities based on OpenStreetMap data or not, use the following methods: + +```ts +map.showOsmBuildings() => void +map.hideOsmBuildings() => void +map.toggleOsmBuildings() => void +``` diff --git a/docs/api-reference/map/map.md b/docs/api-reference/map/map.md new file mode 100644 index 0000000..cef74ab --- /dev/null +++ b/docs/api-reference/map/map.md @@ -0,0 +1,116 @@ +--- +sidebar_label: Overview +slug: overview +sidebar_position: 1 +--- + +# Embedding the map viewer + +Smplr.js makes a `smplr` object available on the global scope. One of the classes provided under this object is the `Map` class. It provides the API necessary to render the Smplrspace map viewer, a custom pre-configured Mapbox-based map which provide all the feature of Mapbox, plus Smplrspace specific features to render your spaces, add 3D cities based on OpenStreetMap data, add data layers, and more. + +## Constructor + +To create a Map instance, initialise it as follow. + +```ts +const map = new smplr.Map({ + clientToken: string, + containerId: string, + disableErrorReporting?: boolean, +}) => Map +``` + +- `clientToken` is an API token that is used to authenticate client-side requests. It is safe to have it exposed in your client code. You can manage your organisation's tokens in the Smplrspace app, by heading to the Developers page from the main menu. [More info](/guides/embedding#client-tokens). +- `containerId` is the "id" of the html "div" container where smplr.js should render the viewer, something like "smplr-container" that can be found in your html. Only ids are supported, not classes. +- `disableErrorReporting` - _optional_ - can be set to "true" to disable the automated reporting of errors to our 3rd party error tracking tool, [Sentry](https://sentry.io/). We have discovered that Sentry's instrumentation could make it seem as if all network requests originated from smplr.js. Unfortunately, there is nothing simple we can do on our side to avoid that. If this is an issue for you, you can disable Sentry altogether. The tradeoff is that we will not automatically detect errors hapenning in your integration, and you may need to be more proactive to report them for us to roll out fixes. + +## Interactive map viewer session + +### Start the viewer + +To initiate an interactive viewer session, use the following code. + +```ts +map.startViewer({ + spaceIds?: string[] + osmBuildings?: boolean + hash?: boolean + fitNewSpacesInScreen?: boolean + loadingMessage?: string + forceLoader?: boolean + onReady?: () => void + onError?: (errorMessage: string) => void + onSpaceClick?: ({ space, levelIndex }: { space: object | undefined; levelIndex: number }) => void +}) => Promise +``` + +- `spaceIds` - _optional_ - lets you specify the Smplrspace ID of the spaces to render on the map when initializing the viewer. You can also do that dynamically as described on the [Building page](/api-reference/map/buildings). +- `osmBuildings` - _optional_ - lets you choose whether to render or not cities in 3D. City buildings data comes from OpenStreetMap and is automatically rendered in 3D. You can also do that dynamically as described in [3D cities](/api-reference/map/buildings#3d-cities). _Default value: true_. +- `hash` - _optional_ - lets you choose whether to automatically sync the map location to the hash fragment of the page's URL. This makes it for easy to share links to specific map locations. It relies on Mapbox's corresponding [parameter](https://docs.mapbox.com/mapbox-gl-js/api/map/#map-parameters). _Default value: false_. +- `fitNewSpacesInScreen` - _optional_ - lets you choose whether to automatically recenter the map to fit all the spaces when the spaces rendered on the map change. You can also center the map using [`fitAllSpacesInScreen`](#fit-all-spaces-in-screen). \_Default value: true. +- `loadingMessage` - _optional_ - lets you override the text displayed while the space is loading. This can be change dynamically as well, see [UI controls](#ui-controls). _Default value: "Loading map"_. +- `forceLoader` - _optional_ - provides programmatic control to whether the loader should be displayed or not. By default we display it while loading the map and initial spaces provided by `spaceIds`, but you can control this if you load your own data as well. This can be change dynamically as well, see [UI controls](#ui-controls). \_Default value: false. +- `onReady` - _optional_ - is called once the viewer's initial render is done. You may alternatively use the promise returned by startViewer, which resolves when the viewer is ready. +- `onError` - _optional_ - is called if an error occur while starting the viewer. You may alternatively use the promise returned by startViewer to catch errors. +- `onSpaceClick` - _optional_ - is called when the user clicks a 3D space, and provide data about which space and which level where clicked. + +Calling `startViewer` returns a `Promise` ([MDN docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)) which resolves when the viewer is ready. This lets you use `Promise.then().catch()` or `async/await` with a `try/catch` block to react when the viewer is ready, or to handle errors that may occur. It is an alternative to providing `onReady` and `onError` callback methods. You may choose the option that suits the most your environment or coding style. + +### Stop the viewer + +To stop the viewer, dispose of resources it allocated, and clear the container in which it is rendered back to its original state, call the following function. + +```ts +space.remove() => void +``` + +## Render buildings + +See the dedicated functions you can call to render buildings [on this page](/api-reference/map/buildings). + +## Control the map location + +### Focus on a specific space + +You can change automatically "fly" the map to a specific space, by providing the space's identifier as follow: + +```ts +map.flyToSpace(spaceId: string) => void +``` + +- `spaceId` - unique identifier of the space in Smplrspace, something like "fbc5617e-5a27-4138-851e-839446121b2e". + +### Fit all spaces in screen + +You can change automatically "fly" the map to an overview point, showing all rendered spaces, as follow: + +```ts +map.fitAllSpacesInScreen() => void +``` + +## UI controls + +### Change the loading message + +You can change the loading message any time as follow. This doesn't impact whether the loader is displayed or not. + +```ts +map.updateLoadingMessage(message: string) => void +``` + +### Control the loader + +You can control whether the loader is displayed or not anytime with the following functions. + +```ts +map.showLoader() => void +map.hideLoader() => void +``` + +## Full Mapbox SDK + +The Smplrspace map viewer is built on top of [Mapbox GL JS](https://docs.mapbox.com/mapbox-gl-js/guides). We provide a number of features dedicated to Smplrspace use-cases, but you can also build anything you want by accessing the full Mapbox SDK as below: + +```ts +map.mapbox() => mapboxgl.Map | undefined +``` diff --git a/docs/api-reference/queryclient/_category_.json b/docs/api-reference/queryclient/_category_.json index 3169cf2..f819929 100644 --- a/docs/api-reference/queryclient/_category_.json +++ b/docs/api-reference/queryclient/_category_.json @@ -1,4 +1,4 @@ { "label": "QueryClient", - "position": 2 + "position": 3 } diff --git a/docs/api-reference/queryclient/doors-windows.md b/docs/api-reference/queryclient/doors-windows.md new file mode 100644 index 0000000..6630cc9 --- /dev/null +++ b/docs/api-reference/queryclient/doors-windows.md @@ -0,0 +1,137 @@ +--- +sidebar_position: 5 +--- + +# Doors & windows + +## Opening interface + +Doors and windows are the same thing under the hood in Smplrspace, we call them wall "openings". Multiple queries in this page return objects of the type `Opening` described below: + +```ts +interface Opening { + id: string; + name: string; + dimensions: { + width: number; + height: number; + baseHeight: number; + }; + options: object; + coordinates: { + levelIndex: number; + x: number; + z: number; + elevation: number; + }[]; +} +``` + +- `id` - unique identifier of this particular opening. +- `name` - name given to the furniture in the editor. It could be an empty string. +- `dimensions.width` - horizontal width of the opening in centimeters. +- `dimensions.baseHeight` - distance between the ground and the bottom of the opening. It is usually 0 for doors and positive for windows. +- `dimensions.height` - distance between the bottom and the top of the opening. +- `options` - contains all sorts of options selected in the editor and used to render the opening. + +## getAllDoorsInSpace + +To list all doors from a space, you can call the following query. + +```ts +smplrClient.getAllDoorsInSpace(id: string): Promise +``` + +- `id` - unique identifier of the space in Smplrspace, something like "fbc5617e-5a27-4138-851e-839446121b2e". +- `Opening` - this main interface is described [here](#opening-interface). + +## getAllDoorsInSpaceFromCache + +This is the synchronous equivalent of the query right above. + +```ts +smplrClient.getAllDoorsInSpaceFromCache(id: string): Opening[] +``` + +where `id` and `Opening` are as defined in `getAllDoorsInSpace`. + +## getDoorsOnLevel + +To list all doors from a single level in a space, you can call the following query. + +```ts +smplrClient.getDoorsOnLevel({ + spaceId: string, + levelIndex: number +}): Promise +``` + +- `spaceId` - unique identifier of the space in Smplrspace, something like "fbc5617e-5a27-4138-851e-839446121b2e". +- `levelIndex` - zero-based index of the level. Refer to the [Opening interface](#Opening-interface) to learn more. +- `Opening` - this main interface is described [here](#opening-interface). + +## getDoorsOnLevelFromCache + +This is the synchronous equivalent of the query right above. + +```ts +smplrClient.getDoorsOnLevelFromCache({ + spaceId: string, + levelIndex: number +}): Opening[] +``` + +where `spaceId`, `levelIndex`, and `Opening` are as defined in `getDoorsOnLevel`. + +## getAllWindowsInSpace + +To list all windows from a space, you can call the following query. + +```ts +smplrClient.getAllWindowsInSpace(id: string): Promise +``` + +- `id` - unique identifier of the space in Smplrspace, something like "fbc5617e-5a27-4138-851e-839446121b2e". +- `Opening` - this main interface is described [here](#opening-interface). + +## getAllWindowsInSpaceFromCache + +This is the synchronous equivalent of the query right above. + +```ts +smplrClient.getAllWindowsInSpaceFromCache(id: string): Opening[] +``` + +where `id` and `Opening` are as defined in `getAllWindowsInSpace`. + +## getWindowsOnLevel + +To list all windows from a single level in a space, you can call the following query. + +```ts +smplrClient.getWindowsOnLevel({ + spaceId: string, + levelIndex: number +}): Promise +``` + +- `spaceId` - unique identifier of the space in Smplrspace, something like "fbc5617e-5a27-4138-851e-839446121b2e". +- `levelIndex` - zero-based index of the level. Refer to the [Opening interface](#Opening-interface) to learn more. +- `Opening` - this main interface is described [here](#opening-interface). + +## getWindowsOnLevelFromCache + +This is the synchronous equivalent of the query right above. + +```ts +smplrClient.getWindowsOnLevelFromCache({ + spaceId: string, + levelIndex: number +}): Opening[] +``` + +where `spaceId`, `levelIndex`, and `Opening` are as defined in `getDoorsOnLevel`. + +## Need any other data? + +[Get in touch](mailto:support@smplrspace.com) with any use-case that would require new queries to be exposed. diff --git a/docs/api-reference/queryclient/geometry.md b/docs/api-reference/queryclient/geometry.md index bd05e66..568e8bb 100644 --- a/docs/api-reference/queryclient/geometry.md +++ b/docs/api-reference/queryclient/geometry.md @@ -112,10 +112,14 @@ smplrClient.getLevelBoundingBoxFromCache({ spaceId: string, levelIndex: number, padding?: number -}): BoundingBox +}): { + levelIndex: number, + x: number, + z: number +}[] ``` -where `spaceId`, `levelIndex`, `padding`, and `BoundingBox` are as defined in `getLevelBoundingBox`. +where `spaceId`, `levelIndex`, and `padding` are as defined in `getLevelBoundingBox`. ## getPointsConcaveHull @@ -169,6 +173,41 @@ smplrClient.getLinesConcaveHull({ - `simplify` - _optional_ - whether the returned hull should be simplified, which means consecutive points that are aligned will be removed to keep only the first and the last. _Default value: true_ - `simplifyTolerance` - _optional_ - authorized distance from the alignment used during the simplification process, given in meters. _Default value: 0.005_ +## getLevelAutomaticGround + +To get the automatic ground of the entire floor plate of a space, you can call the following query. The automatic ground is the [continuous concave hull](#getlinesconcavehull) of all the walls of the level put together. It may be enabled or disabled in the editor, but the value here will return a valid hull if the level exists and has walls. + +```ts +smplrClient.getLevelAutomaticGround({ + spaceId: string, + levelIndex: number, +}): Promise<{ + levelIndex: number, + x: number, + z: number +}[] | null> +``` + +- `spaceId` - unique identifier of the space in Smplrspace, something like "fbc5617e-5a27-4138-851e-839446121b2e". +- `levelIndex` - zero-based index of the level. Refer to the [Furniture interface](/api-reference/queryclient/furniture#furniture-interface) to learn more. + +## getLevelAutomaticGroundFromCache + +This is the synchronous equivalent of the query right above. + +```ts +smplrClient.getLevelAutomaticGroundFromCache({ + spaceId: string, + levelIndex: number, +}): { + levelIndex: number, + x: number, + z: number +}[] | null +``` + +where `spaceId`, and `levelIndex` are as defined in `getLevelAutomaticGround`. + ## isPointInPolygon To know whether a point is contained within an area defined by a polygon, you can call the following query. diff --git a/docs/api-reference/queryclient/queryclient.md b/docs/api-reference/queryclient/queryclient.md index f84faee..ad4e110 100644 --- a/docs/api-reference/queryclient/queryclient.md +++ b/docs/api-reference/queryclient/queryclient.md @@ -29,7 +29,7 @@ const smplrClient = new smplr.QueryClient({ ``` - `organizationId` is the unique identifier of your organization in Smplrspace, something like "fbc5617e-5a27-4138-851e-839446121b2e". Personal accounts are also treated as "personal organization". To get your organization's ID, head to the Developers page from the main menu. -- `clientToken` is an API token that is used to authenticate client-side requests. It is safe to have it exposed in your client code. You can manage your organisation's tokens in the Smplrspace app, by heading to the Developers page from the main menu. +- `clientToken` is an API token that is used to authenticate client-side requests. It is safe to have it exposed in your client code. You can manage your organisation's tokens in the Smplrspace app, by heading to the Developers page from the main menu. [More info](/guides/embedding#client-tokens). ## How to use it diff --git a/docs/api-reference/space/custom-ux.md b/docs/api-reference/space/custom-ux.md index 31bad6b..76d5479 100644 --- a/docs/api-reference/space/custom-ux.md +++ b/docs/api-reference/space/custom-ux.md @@ -24,6 +24,8 @@ interface RenderOptions { maxHeightCm?: number; showStructuralWalls?: boolean; }; + doors?: boolean; + windows?: boolean; objects?: boolean; annotations?: boolean; compass?: boolean; @@ -42,6 +44,8 @@ interface RenderOptions { - `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)_ +- `doors` - _optional_ - set this value to control whether the doors are rendered or not. _Default value: true_ +- `windows` - _optional_ - set this value to control whether the windows are rendered or not. _Default value: true_ - `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)_ @@ -76,6 +80,7 @@ space.startViewer({ disableCameraRotation?: boolean, autoRotate?: boolean, hideNavigationButtons?: boolean + hideLevelPicker?: boolean }) => void ``` @@ -88,6 +93,7 @@ space.startViewer({ - `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_ - `autoRotate` - _optional_ - set this to true to have the viewer spin around the space automatically. You can also start, set the rotation speed, and stop the rotation as described [below](#auto-rotate-the-viewer). _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_ +- `hideLevelPicker` - _optional_ - set this to true if you want to remove the level picker from the viewer. Levels can still be controlled programmatically, so you could use your own buttons or logic. _Default value: false_ ## Viewer controls diff --git a/docs/api-reference/space/data-layers.md b/docs/api-reference/space/data-layers.md index 38b08d0..396e3b8 100644 --- a/docs/api-reference/space/data-layers.md +++ b/docs/api-reference/space/data-layers.md @@ -14,17 +14,17 @@ Some options correspond to generic behaviours that are shared by all interactive space.addDataLayer({ // ...layerDefinition, tooltip?: (dataElement: object) => string, - onClick?: (dataElement: object) => void, - onHover?: (dataElement: object) => void, - onHoverOut?: (dataElement: object) => void + onClick?: (dataElement: object, event: PointerEvent) => void, + onHover?: (dataElement: object, event: LimitedPointerEvent) => void, + onHoverOut?: (dataElement: object, event: LimitedPointerEvent) => void }) => DataLayerController ``` - `...layerDefinition` - refer to the [overview](./overview#data-layers) page. - `tooltip` - _optional_ - is taking the newly hovered data element as argument and should return the content of the tooltip to render. It is called once when the pointer starts to hover a data element. Built-in tooltips are text only, newlines are supported by using [multi-line template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#multi-line_strings). If you need HTML/CSS in your tooltips, check the [custom tooltips example](/examples/custom-tooltips/). -- `onClick` - _optional_ - is taking the data element that was clicked as argument. It is called each time a click or tap event happens. -- `onHover` - _optional_ - is taking the newly hovered data element as argument. It is called once when the pointer starts to hover a data element. -- `onHoverOut` - _optional_ - is taking the previously hovered data element as argument. It is called once when the pointer stops hovering a data element. +- `onClick` - _optional_ - is taking the data element that was clicked as argument, as well as the Javascript [pointer event](https://developer.mozilla.org/en-US/docs/Web/API/PointerEvent) that triggered the click. It is called each time a click or tap event happens. +- `onHover` - _optional_ - is taking the newly hovered data element as argument, as well as a limited (due to the rendering engine's internals) "pointer event" that triggered the handler. The limited event only includes the coordinates within the viewer of the pointer at the time when the event was triggered. The handler is called once when the pointer starts to hover a data element. +- `onHoverOut` - _optional_ - is taking the previously hovered data element as argument, as well as the same limited "pointer event" as for `onHover`. The handler is called once when the pointer stops hovering a data element. You may use the `onClick`, `onHover` and `onHoverOut` handlers to build custom behaviours in your app that respond to interactions happening in the floor plan. diff --git a/docs/api-reference/space/space.md b/docs/api-reference/space/space.md index 51212f4..df40b4e 100644 --- a/docs/api-reference/space/space.md +++ b/docs/api-reference/space/space.md @@ -23,7 +23,7 @@ const space = new smplr.Space({ ``` - `spaceId` is the unique identifier of the space in Smplrspace, something like "fbc5617e-5a27-4138-851e-839446121b2e". -- ⚠️ **BREAKING CHANGE** ⚠️ — `clientToken` is an API token that is used to authenticate client-side requests. It is safe to have it exposed in your client code. You can manage your organisation's tokens in the Smplrspace app, by heading to the Developers page from the main menu. Client tokens are being rolled out and currently not enforced, starting October 1st 2022, request with no token or an invalid token will be rejected. [More info](/guides/embedding#client-tokens). +- `clientToken` is an API token that is used to authenticate client-side requests. It is safe to have it exposed in your client code. You can manage your organisation's tokens in the Smplrspace app, by heading to the Developers page from the main menu. [More info](/guides/embedding#client-tokens). - `containerId` is the "id" of the html "div" container where smplr.js should render the viewer, something like "smplr-container" that can be found in your html. Only ids are supported, not classes. - `disableErrorReporting` - _optional_ - can be set to "true" to disable the automated reporting of errors to our 3rd party error tracking tool, [Sentry](https://sentry.io/). We have discovered that Sentry's instrumentation could make it seem as if all network requests originated from smplr.js. Unfortunately, there is nothing simple we can do on our side to avoid that. If this is an issue for you, you can disable Sentry altogether. The tradeoff is that we will not automatically detect errors hapenning in your integration, and you may need to be more proactive to report them for us to roll out fixes. - `whiteLabel` - _optional_ - can be set to "true" to remove the "Powered by Smplrspace" attribution from the viewer. This is a paid add-on. You can check if it is enabled from the Organization settings page. [Get in touch](mailto:hello@smplrspace.com) to learn more.