@kinesisjs/angular
v0.2.1
Published
Angular Signals / RxJS wrapper for Kinesis.js
Maintainers
Readme
@kinesisjs/angular
Angular Signals / RxJS wrapper for Kinesis.js — one-line directive setup.
Angular lifecycle and reactive-binding layer on top of @kinesisjs/core and @kinesisjs/openlayers.
Scope
KinesisMapDirective— standalone directive, one-line declarative setupkinesisTrackerfactory — programmatic use inside services or route resolvers- Automatic binding for both
Signal<Position[]>andObservable<Position[]> - Automatic teardown via
DestroyRef— no manualtracker.destroy()required - Angular 17+ standalone APIs
Installation
pnpm add @kinesisjs/core @kinesisjs/openlayers @kinesisjs/angular olPeer dependencies: @angular/core >=17, @angular/common >=17, rxjs >=7, ol >=8.
Usage
import { Component, inject } from '@angular/core';
import { KinesisMapDirective } from '@kinesisjs/angular';
@Component({
selector: 'app-live-map',
standalone: true,
imports: [KinesisMapDirective],
template: `
<div
kinesisMap
[positions]="positions"
[center]="[29.0, 41.0]"
[zoom]="10"
[interpolation]="'adaptive'"
class="map-container"
></div>
`,
styles: [
`
.map-container {
width: 100%;
height: 600px;
}
`,
],
})
export class LiveMapComponent {
positions = inject(PositionsService).positions; // Signal<Position[]>
}Programmatic factory
Use kinesisTracker(...) when you need control outside a template — for example inside a service or route resolver, or when you manage the OpenLayers map yourself:
@Injectable({ providedIn: 'root' })
export class TrackingService {
private readonly map = inject(MapService).map;
private readonly positions = inject(PositionsService).positions;
tracker = kinesisTracker({
map: this.map,
positions: this.positions,
trackerOptions: { interpolation: 'adaptive' },
adapterOptions: {
style: createVehicleStyle({ icon: '/car.png' }),
},
});
}Note: kinesisTracker(...) must be called inside an Angular injection context (constructor, field initializer, or runInInjectionContext).
Directive inputs
| Input | Type | Default | Description |
| --------------------- | --------------------------------------------------------------------------------- | -------------- | ---------------------------- |
| positions ⭐ | Signal<Position[]> \| Observable<Position[]> | — | Position source (required) |
| center | [number, number] | [29.0, 41.0] | Initial map centre (lng/lat) |
| zoom | number | 10 | Initial zoom |
| interpolation | 'linear' \| 'cubic' \| 'geodesic' \| 'none' \| 'adaptive' \| CustomInterpolator | 'linear' | Interpolation behaviour |
| maxInterpolationGap | number | 30000 | Milliseconds |
| warningThreshold | number | 60000 | Milliseconds |
| staleThreshold | number | 600000 | Milliseconds |
| ingestThrottle | number | 100 | Milliseconds |
| vehicleStyle | VehicleStyleProvider | — | OpenLayers style provider |
Accessing the tracker
@ViewChild('map', { read: KinesisMapDirective }) directive!: KinesisMapDirective;
ngAfterViewInit() {
const tracker = this.directive.getTracker(); // Tracker | undefined
const map = this.directive.getMap(); // OLMap | undefined
tracker?.on('vehiclewarning', ({ vehicleId }) => /* apply visual hint */);
tracker?.markCompleted('v1');
console.log(tracker?.getStats());
}Public API
export { KinesisMapDirective, kinesisTracker, bindPositions };
export type { KinesisTrackerConfig };