Modlet
The GIS modlet is designed such that map rendering engines can be swapped without having to change the usage of
the web components. This is achieved by having web components that interfact with the rendering engine through a
standardized interface.
Types
The GIS modlet exports its types under the Gis namespace, you can find this file in src/lib/aoh/gis/types.d.ts.
When referring to types in this documentation, you will often see the them prefixed with the "Gis" namespace, for
example, Gis.GeoEntityType - this refers to types that can be found in the file mentioned above.
Components
Under the src/lib/aoh/gis/components folder, you'll find these ready-to-use Svelte components.
Other components you find here that are not mentioned in these documentation are either still in-development and not ready for use, or meant for internal use only, you may however use them at your own risk.
MapCesiumMapEngineProviderMapBaseLayerProviderMapXyzSourceProviderMapEntityLayerProviderMapEntityProviderMapLayerManagerMapBookmarkManager
Map Component
The Map component is the heart of the GIS modlet, it contains all the glue to tie the Map components to the
rendering engine. The map must always be wrapped with an engine provider. At present, we only have one engine provider
(CesiumMapEngineProvider).
A bindable Gis.GisMap object is exposed if you need to get a reference to the map if necessary, but we recommend you
create more Svelte Components that get the Gis.GisMap from the Svelte context instead if you want to write reusable
components that could be contributed to the GIS modlet in the future.
<script lang="ts">
import Map from "$lib/aoh/gis/components/Map/index.svelte";
import CesiumMapEngineProvider from "$lib/aoh/gis/components/engines/CesiumMapEngineProvider/index.svelte";
let map: Gis.GisMap;
...
</script>
<CesiumMapEngineProvider>
<Map bind:map {...} >
...
</Map>
</CesiumMapEngineProvider>
Example
<Map
initial_camera_view={{
position: [103.8189, 1.3521] // position of Singapore
zoom: 8 // see `Gis.ZoomLevel` for more information
}}
rtus_seh_url={"http://rtus-seh.example.com"}
rtus_map_name={"gis"}
user_id={data.user?.sub}
tenant_id={data.user?.active_tenant?.tenant_id}
>
...
</Map>
initial_camera_view
This property expects a Gis.CameraView, which contains all the necessary information to position and point a camera
in the map.
rtus_seh_url
The URL to the RTUS - SEH service - this for the SSE connection that will continually update the map with entities.
rtus_map_name
The name of the RTUS map that stores all the GIS state: this is the same map name as what you have declared in the
GIS service.
See gis.rtus.map_name and PUBLIC_GIS_RTUS_MAP_NAME
user_id
Currently not actually used for any purpose but checked during map initialization for legacy reasons. Must not be a falsy value for the map to be initialized. Just pass in any truthy value to proceed.
tenant_id
The tenant_id of the RTUS map to subscribe to - you should be using the tenant_id of the user for this property.
CesiumMapEngineProvider Component
The implementation of the interface can be found within the src/lib/aoh/gis/components/engines folder. We currently
support the CesiumJS render.
MapBaseLayerProvider Component
The MapBaseLayerProvider provides the map with base layers. This component expects one or more base layer sources to
be provided as children. See MapXyzSourceProvider.
Examples:
<MapBaseLayerProvider layer_name="Street" is_visible={true} options={{ brightness: 0.5 }}>
<MapXyzSourceProvider url={`https://tile.openstreetmap.org/{z}/{x}/{y}.png`}></MapXyzSourceProvider>
</MapBaseLayerProvider>
You can group multiple sources under one layer to control their visiblity together. These sources will all appear as
just one layer in the Layer Manager UI. The order that they appear will be based on the order they are instantiated
in code here.
<MapBaseLayerProvider layer_name="Street" is_visible={true} options={{ brightness: 0.5 }}>
<MapXyzSourceProvider
url={`https://api.maptiler.com/tiles/hillshade/{z}/{x}/{y}.webp?key=0123456789`}
></MapXyzSourceProvider>
<MapXyzSourceProvider url={`https://tile.openstreetmap.org/{z}/{x}/{y}.png`}></MapXyzSourceProvider>
</MapBaseLayerProvider>
layer_name
The name of the layer, this is used by the MapLayerManager as a label for toggling the visibility.
is_visible
A boolean true or false value to determine if the layer is visible by default.
brightness
A brightness modifier to darken the layer. This is particularly useful for controlling translucent layers or to make certain layers stand out.
This property is scopes under an options object:
MapXyzSourceProvider Component
The MapXyzSourceProvider allows you to add an XYZ source URL that serves map tiles in the XYZ (a.k.a
Slippy Map Tilenames) format.
url
The tile source URL to connect to. The varies based on different flavours of servers, but a sample that uses an API key for authentication would look like this:
https://maptiles.p.rapidapi.com/local/osm/v1/zoom/x/y.png?rapidapi-key=YOUR-KEY
MapEntityLayerProvider Component
The MapEntityLayerProvider represents a layer that may contain one or more entity (and entity kinds). You need
to also pass in a MapEntityProvider as a child snippet to provide the necessary information for
to render entities in this layer.
Examples:
<MapEntityLayerProvider layer_name="Aircraft" is_visible>
<MapEntityProvider kind={"aircraft"}>...</MapEntityProvider>
</MapEntityLayerProvider>
layer_name
The name of the layer, this is used by the MapLayerManager as a label for toggling the visibility.
is_visible
A boolean true or false value to determine if the layer is visible by default.
MapEntityProvider Component
The MapEntityProvider requires a snippet to be supplied for a chosen "kind".
In the following example, for all geoentities of kind "example", a floating, red <div> that shows the value of
example_property gets rendered. You can supply any snippet you want, and you can reference the geoentity's properties
via the snippet's parameters. The snippet will get rendered at the position
of the entity.geojson.geometry.coordinates (this is for Point features).
<MapEntityLayerProvider layer_name="Example Layer">
<MapEntityProvider kind={"example"}>
{#snippet children(entity: Gis.MapEntity<{example_property: string}>)}
{#if entity.geojson.type === "Feature"}
<div class="p-4 bg-red-500">{entity.geojson.properties.example_property}</div>
{/if}
{/snippet}
</MapEntityProvider>
</MapEntityLayerProvider>
For lines, polygons etc. (shapes more complex than points) "geom" information needs to be specified for the renderer.
<MapEntityLayerProvider layer_name="Airport">
<MapEntityProvider
kind={"airport"}
geom_style={{
fill: "#999999",
"fill-opacity": 0.5,
stroke: "#FF0000",
"stroke-opacity": 1,
}}
on_geom_click={(map_entity: Gis.MapEntity<Record<string, unknown>>) => {
if (!map_entity.set_entity_style) {
return;
}
map_entity.set_entity_style({
fill: `rgb(${Math.floor(Math.random() * 255)} ${Math.floor(Math.random() * 255)} ${Math.floor(
Math.random() * 255
)})`,
"fill-opacity": 0.5,
stroke: "#FF0000",
"stroke-opacity": 1,
});
}}
on_geom_hover={(map_entity: Gis.MapEntity<Record<string, unknown>>) => {
if (!map_entity.set_entity_style) {
return;
}
map_entity.set_entity_style({
fill: `rgb(${Math.floor(Math.random() * 255)} ${Math.floor(Math.random() * 255)} ${Math.floor(
Math.random() * 255
)})`,
"fill-opacity": 0.5,
stroke: "#FF0000",
"stroke-opacity": 1,
});
}}
></MapEntityProvider>
</MapEntityLayerProvider>
MapLayerManager Component
The MapLayerManager is a prebuilt UI component that adds map layer controls as a UI overlay.
It expects to be passed a child snippet which will be used as the button to open the manager. The following example
shows the child snippet with a <Button> component:
<MapLayerManager>
<Button>Layers</Button>
</MapLayerManager>
MapBookmarkManager Component
The MapBookmarkManager is a prebuilt UI component that adds controls to add and delete bookmarks.
It expects to be passed a child snippet which will be used as the button to open the manager. It also expects an array
of Gis.MapBookmarks to render on initialization.
The following example shows the child snippet with a <Button> component:
<MapBookmarkManager {bookmarks}>
<Button>Bookmarks</Button>
</MapBookmarkManager>
Example Page
A full example page, complete with server functions in use is installed by default as an example at:
src/routes/(private)/aoh/gis/+page.server.tssrc/routes/(private)/aoh/gis/+page.svelte