Advanced
Raw map access, synced viewports, and the map context service.
Using the Map Instance
# The mapReady output hands you the raw maplibre-gl Map instance for anything the declarative API doesn't cover. Here it drives flyTo on a globe projection.
import { Component } from '@angular/core';
import type { Map as MapLibreMap } from 'maplibre-gl';
import { MapComponent } from 'ng-mapcn';
@Component({
selector: 'app-globe-flyto',
standalone: true,
imports: [MapComponent],
template: `
<div class="h-[420px]">
<ng-map
[center]="[0, 20]"
[zoom]="1.5"
[projection]="{ type: 'globe' }"
(mapReady)="onMapReady($event)"
/>
</div>
`,
})
export class GlobeFlytoComponent {
private map?: MapLibreMap;
onMapReady(map: MapLibreMap): void {
this.map = map;
}
flyTo(center: [number, number]): void {
// Full access to the raw MapLibre instance.
this.map?.flyTo({ center, zoom: 8, duration: 2500, essential: true });
}
}Fly to Markers
# Combine markerClick with the map instance: click a marker to fly to its city.
<ng-map [center]="[10, 48]" [zoom]="4" (mapReady)="onMapReady($event)">
@for (city of cities; track city.name) {
<ng-map-marker
[longitude]="city.lng"
[latitude]="city.lat"
(markerClick)="flyTo(city)"
>
<ng-marker-content>
<div class="size-3.5 cursor-pointer rounded-full border-2 border-white bg-blue-500 shadow-lg"></div>
<ng-marker-label position="top">{{ city.name }}</ng-marker-label>
</ng-marker-content>
</ng-map-marker>
}
</ng-map>Synced Viewports
# Two maps sharing one controlled viewport signal. Pan or zoom either map and the other follows.
import { Component, signal } from '@angular/core';
import { MapComponent, MapViewport } from 'ng-mapcn';
@Component({
selector: 'app-synced-viewports',
standalone: true,
imports: [MapComponent],
template: `
<div class="grid h-[420px] grid-cols-2 gap-2">
<!-- Single source of truth shared by both maps (controlled viewport). -->
<ng-map [viewport]="viewport()" (viewportChange)="viewport.set($event)" />
<ng-map [viewport]="viewport()" (viewportChange)="viewport.set($event)" />
</div>
`,
})
export class SyncedViewportsComponent {
readonly viewport = signal<MapViewport>({
center: [-46.63, -23.55],
zoom: 10,
bearing: 0,
pitch: 0,
});
}Using the Context Service
# Build your own map components: any component projected inside ng-map can inject MapContextService to access the map instance, isLoaded, and the resolved theme — the Angular equivalent of mapcn's useMap() hook.
import { Component, effect, inject } from '@angular/core';
import { MapContextService } from 'ng-mapcn';
// Any component placed inside <ng-map> can inject the map context —
// the Angular equivalent of mapcn's useMap() hook.
@Component({
selector: 'app-my-custom-control',
standalone: true,
template: `...`,
})
export class MyCustomControlComponent {
private readonly ctx = inject(MapContextService);
constructor() {
effect(() => {
if (!this.ctx.isLoaded()) return;
const map = this.ctx.map(); // raw maplibre-gl Map
// add sources, layers, event handlers...
});
}
}