Arcs
Curved great-circle-style lines between coordinate pairs.
Basic Arc
#ng-map-arc renders smooth Bézier arcs from from/to pairs — here on a globe projection, connecting London to cities around the world.
import { Component } from '@angular/core';
import { MapArcComponent, MapArcDatum, MapComponent } from 'ng-mapcn';
const hub = { name: 'London', lng: -0.1276, lat: 51.5074 };
const destinations = [
{ name: 'New York', lng: -74.006, lat: 40.7128 },
{ name: 'São Paulo', lng: -46.6333, lat: -23.5505 },
{ name: 'Cape Town', lng: 18.4241, lat: -33.9249 },
{ name: 'Dubai', lng: 55.2708, lat: 25.2048 },
// ...
];
@Component({
selector: 'app-basic-arc',
standalone: true,
imports: [MapComponent, MapArcComponent],
template: `
<div class="h-[420px]">
<ng-map [center]="[-0.1276, 51.5074]" [zoom]="1" [projection]="{ type: 'globe' }">
<ng-map-arc
[data]="arcs"
[paint]="{ 'line-color': '#3b82f6', 'line-dasharray': [2, 2] }"
[interactive]="false"
/>
</ng-map>
</div>
`,
})
export class BasicArcComponent {
readonly arcs: MapArcDatum[] = destinations.map((dest) => ({
id: dest.name,
from: [hub.lng, hub.lat],
to: [dest.lng, dest.lat],
}));
}Interactive Arcs
# Extra datum properties drive the paint via expressions, and hoverPaint + arcHover power the popup. Hover a lane to see its details.
Air
Sea
import { Component, signal } from '@angular/core';
import type { ExpressionSpecification } from 'maplibre-gl';
import {
MapArcComponent,
MapArcDatum,
MapArcEvent,
MapComponent,
MapPopupComponent,
} from 'ng-mapcn';
interface Lane extends MapArcDatum {
origin: string;
destination: string;
volume: string;
mode: 'air' | 'sea';
}
const lanes: Lane[] = [
{ id: 'shg-lax', origin: 'Shanghai', destination: 'Los Angeles',
from: [121.4737, 31.2304], to: [-118.2437, 34.0522],
volume: '24.8k TEU', mode: 'sea' },
{ id: 'dxb-jfk', origin: 'Dubai', destination: 'New York',
from: [55.2708, 25.2048], to: [-74.006, 40.7128],
volume: '980 tons', mode: 'air' },
// ...
];
// Extra datum properties are exposed to paint expressions via ["get", ...]
const modeColor: ExpressionSpecification = [
'match', ['get', 'mode'],
'air', '#a78bfa',
'sea', '#34d399',
'#888',
];
@Component({
selector: 'app-interactive-arc',
standalone: true,
imports: [MapComponent, MapArcComponent, MapPopupComponent],
template: `
<div class="h-[420px]">
<ng-map [center]="[20, 20]" [zoom]="0.8">
<ng-map-arc
[data]="lanes"
[paint]="{ 'line-color': modeColor, 'line-width': 1.5 }"
[hoverPaint]="{ 'line-width': 3, 'line-opacity': 1 }"
(arcHover)="onHover($event)"
/>
@if (selected(); as sel) {
<ng-map-popup
[longitude]="sel.longitude"
[latitude]="sel.latitude"
[offset]="12"
[closeOnClick]="false"
className="ng-popup-passthrough"
>
{{ sel.lane.origin }} → {{ sel.lane.destination }} · {{ sel.lane.volume }}
</ng-map-popup>
}
</ng-map>
</div>
`,
})
export class InteractiveArcComponent {
readonly lanes = lanes;
readonly modeColor = modeColor;
readonly selected = signal<{
lane: Lane;
longitude: number;
latitude: number;
} | null>(null);
onHover(event: MapArcEvent<Lane> | null): void {
this.selected.set(
event
? { lane: event.arc, longitude: event.longitude, latitude: event.latitude }
: null
);
}
}