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.
Map
CesiumMapEngineProvider
MapBaseLayerProvider
MapXyzSourceProvider
MapEntityLayerProvider
MapEntityProvider
MapLayerManager
MapBookmarkManager
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.ts
src/routes/(private)/aoh/gis/+page.svelte