Skip to content

MapLibre

MapLibre is an open-source library for rendering interactive vector maps with WebGL. Element supports Angular applications that use @maplibre/ngx-maplibre-gl with control styles, a theme-aware map style, and translated control labels.

Usage

MapLibre exposes its map, controls, sources, and layers as composable Angular components and directives. Applications remain responsible for configuring and composing the map.

When to use

  • When direct access to MapLibre features, sources, and layers is required.
  • When map controls and behavior need to be composed for a specific use case.
  • When vector-map rendering and MapLibre's ecosystem are preferred.
  • When 3D features such as pitched views, extruded buildings, or a globe are required.
  • When the high-level Element Maps component does not provide enough flexibility.

Code

See the ngx-maplibre-gl documentation and the MapLibre GL JS documentation for the complete APIs and configuration options.

Required Packages
npm install --save @siemens/element-ng @siemens/map-styles @siemens/element-translate-ng
npm install --save @maplibre/ngx-maplibre-gl maplibre-gl

Configure the MapLibre worker

MapLibre GL JS 6 loads its web worker from a separate file. Add the worker and its shared module to the application assets in angular.json:

{
  "architect": {
    "build": {
      "options": {
        "assets": [
          {
            "glob": "maplibre-gl-{worker,shared}.mjs",
            "input": "node_modules/maplibre-gl/dist",
            "output": "/assets/maplibre/"
          }
        ]
      }
    }
  }
}

Register the worker in the application configuration before creating a map:

import { ApplicationConfig } from '@angular/core';
import { provideMaplibreWorker } from '@maplibre/ngx-maplibre-gl/config';

export const appConfig: ApplicationConfig = {
  providers: [provideMaplibreWorker('assets/maplibre/maplibre-gl-worker.mjs')]
};

Apply Element control styles

Import the Element MapLibre stylesheet in the application's global stylesheet. It provides the required MapLibre layout styles and applies Element styling to controls, popovers, markers, and other map UI.

@use '@siemens/element-ng/maplibre/styles';

Use this stylesheet instead of importing maplibre-gl/dist/maplibre-gl.css separately.

Apply the Element map style

injectSiMapStyle() creates a signal containing the Element MapLibre style. Pass a MapTiler API key to the function and bind the signal value to the map's mapStyle input. The style updates automatically when the Element theme changes.

The function must be called in an Angular injection context, such as a component field initializer.

import { Component } from '@angular/core';
import { MapComponent } from '@maplibre/ngx-maplibre-gl';
import { injectSiMapStyle } from '@siemens/element-ng/maplibre';

@Component({
  selector: 'app-map',
  imports: [MapComponent],
  template: '<mgl-map class="h-100" [mapStyle]="mapStyle()" />'
})
export class AppMapComponent {
  protected readonly mapStyle = injectSiMapStyle('REPLACE_WITH_YOUR_MAPTILER_KEY');
}

Apply translations

injectSiMapTranslations() creates a signal containing translated MapLibre locale strings. It uses the configured Element translation service and updates when the active language changes. Bind the signal value to the map's locale input:

import { Component } from '@angular/core';
import { MapComponent } from '@maplibre/ngx-maplibre-gl';
import { injectSiMapTranslations } from '@siemens/element-ng/maplibre';

@Component({
  selector: 'app-map',
  imports: [MapComponent],
  template: '<mgl-map class="h-100" [locale]="mapTranslations()" />'
})
export class AppMapComponent {
  protected readonly mapTranslations = injectSiMapTranslations();
}

MapLibre example

The following example combines the Element map style and translations with MapLibre controls.

Cluster example

The following example uses SiClusterSourceComponent to cluster GeoJSON points and SiStatusMarkerComponent for unclustered markers. Cluster markers show the number of contained points and their distribution by group or status.

Clicking a cluster frames all of its children and zooms in as far as possible while they stay visible. The animation is skipped when prefers-reduced-motion is set. Zooming stops at clusterMaxZoom, above which points are no longer clustered. Clusters whose children stay within clusterRadius up to that zoom cannot be pulled apart, so they emit clusterClick and open the projected popover instead. Set zoomOnClick to false to always open the popover, as the switch in the example demonstrates.

3D buildings example

MapLibre GL renders maps with WebGL, so the camera can be pitched and vector-tile buildings can be extruded into 3D.

The example pitches the map and adds a fill-extrusion layer on the OpenMapTiles building source. Building height animates in between zoom 15 and 16 using the render_height and render_min_height properties from the tiles.

Custom cluster popover

Use an ng-template with siClusterPopoverTemplate to customize the list of loaded cluster features. This example displays each location's name, description, and status as a selectable list item. Selecting a location updates the status above the map and logs the feature.

The popover handles loading and error states for both default and custom content. The "Load more" button appears after the first batch is loaded. If a request fails, an alert appears at the end of the list and the same button becomes "Retry", preserving focus and already loaded locations. Retrying reloads only the failed batch.

The pageSize input controls how many locations are loaded initially and with each click. Loaded locations stay visible while the next batch loads, with feature actions temporarily disabled. New locations are appended to the list.

Both default and custom content scroll below the fixed header. The centered "Load more" button sits at the end of the scrolling content and moves below newly appended locations. By default, the close button receives initial focus. Focus stays on "Load more" while loading and after items are appended, keeping the button visible. When all locations are loaded and the button disappears, focus moves to the scrolling region, so pressing Enter again does not close the popover.

SiClusterSourceComponent API Documentation

selector
si-cluster-source

Adds a clustered GeoJSON source to a MapLibre map and renders interactive cluster markers.

Cluster markers display the number of contained points and their distribution by group. Status segments can be enabled for ungrouped points by providing statusProperty . Render individual, unclustered points separately with mgl-markers-for-clusters using the same source ID. Positive numeric groups always take precedence over status segments. Status segments apply only when the normalized group value is zero; points without a matching group or status use the ungrouped color.

Clicking a cluster frames all of its children and zooms in as far as possible while they stay visible, up to the zoom at which points stop being clustered. Clusters whose children stay within clusterRadius until then emit clusterClick instead, which opens a projected si-cluster-popover .

Example:

<mgl-map [mapStyle]="mapStyle()">
  <si-cluster-source
    sourceId="locations"
    statusProperty="status"
    [data]="locations"
    (clusterClick)="onClusterClick($event)"
  />

  <mgl-markers-for-clusters source="locations">
    <ng-template let-feature mglPoint>
      <si-status-marker
        [status]="feature.properties?.status"
      />
    </ng-template>
  </mgl-markers-for-clusters>
</mgl-map>

Input Properties

Name Type Default Description
clusterMaxZoom
number undefined Maximum zoom at which points are clustered.
clusterMinPoints
number 2 Minimum number of points required to form a cluster.
clusterRadius
number 50 Cluster radius in pixels.
data
FeatureCollection<Point, GeoJsonProperties> EMPTY_DATA Point feature collection to cluster.
groupColors
ClusterColors 'status' Built-in palette or exact colors indexed by group ID. The built-in 'status' palette contains four colors for numeric groups and is separate from status-based bucketing.
groupProperty
string 'group' Feature property containing the positive numeric group ID.
sourceId
Required
string ID used to register the generated GeoJSON source in MapLibre.
statusProperty
string undefined Top-level feature property containing a MarkerStatus: link not resolved value. Status bucketing is disabled by default and only applies when the normalized group value is zero. Missing or unsupported status values, and groups that do not match a configured bucket, use the ungrouped color. Built-in colors match SiStatusMarkerComponent , with default using accent and unknown using neutral.
See https://maplibre.org/maplibre-style-spec/sources/#clusterproperties
zoomMaxLevel
number undefined Highest zoom used to expand a cluster. Clusters whose children stay within clusterRadius up to this zoom emit clusterClick instead of zooming. Defaults to clusterMaxZoom , because points stop being clustered above it.
zoomOnClick
boolean false Frames the children of a clicked cluster and zooms in as far as possible while they stay visible. Clusters whose children cannot be pulled apart emit clusterClick instead.

Output Properties

Name Type Description
clusterClick
ClusterPoint Emits when a cluster marker is activated and the click did not expand the cluster, either because zoomOnClick is disabled or because the children cannot be pulled apart.

Attributes and Methods

Name Type Default Description
getClusterLeaves(...)
(clusterId: number, limit: number, offset: number) => Promise<ClusterPoint[]> Returns a page of original points belonging to a cluster.
See https://maplibre.org/maplibre-gl-js/docs/API/classes/GeoJSONSource/#getclusterleaves

Parameters

SiClusterPopoverComponent API Documentation

selector
si-cluster-popover

Optional popup with incrementally loaded locations projected into a si-cluster-source .

Input Properties

Name Type Default Description
closeOnMove
boolean true Whether the popup closes when the map moves.
descriptionProperty
string 'description' Feature property displayed as the description in the default list.
labelProperty
string 'name' Feature property displayed in the default list.
maxWidth
string '320px' Maximum width passed to the MapLibre popup.
pageSize
number 8 Number of locations loaded initially and with each "Load more" action.

SiClusterPopoverTemplateDirective API Documentation

selector
[siClusterPopoverTemplate]

Template for custom location content inside si-cluster-popover .

Receives a ClusterPopoverContext: link not resolved with all locations loaded so far. Loading feedback, error recovery, and the "Load more" button are handled by the popover.

No API to document for this.


Except where otherwise noted, content on this site is licensed under MIT License.