@kinesisjs/core · TypeScript-first · framework-agnostic

Smooth real-time vehicle interpolation for .

A TypeScript-first interpolation engine that drops straight into your map. Smooth motion between position updates — WebSocket, polling, or anything else — without writing your own animation loop.

Quick startView on GitHub
MIT<5 KB coreZero runtime deps60fps @ 1000+ vehicles
See the difference · live

Without it, vehicles teleport. With it, they flow.

Both maps read the same position stream at a 2.2 s server period. Left snaps on every update; right runs the Kinesis.js tick loop.

RAW · setCoordinates()no interpolation
server tick → snap
kinesis.js · interpolated60fps
tick(hl) → interpolate
Vehicles7
Server period2.2s
Tick @10000.15ms
Dropped0
What's in the box

A narrow problem, solved to production depth.

Framework-agnostic core

Plain TypeScript. The engine has zero runtime deps — bring Angular, React, or no framework at all.

Fixed memory profile

Ring-slot buffers keep two points per vehicle. Allocation-free hot path, bounded memory across an 8-hour shift.

Adaptive interpolation

Reads the feed period per vehicle and switches between snap, lerp and fade zones — no manual tuning.

Multi-state lifecycle

Vehicles flow through active → warning → stale → completed, with events at every transition.

Built-in sanity checks

Anomalous jumps and sharp turns are caught automatically — fade behavior and cubic fallback, no opt-out.

Error-as-event

Adapter and interpolation failures surface as typed error events — the tick loop never dies.

Reactive binding

The Angular wrapper accepts a Signal or Observable of positions and wires lifecycle to DestroyRef.

Web Worker mode

Move the tick loop off the main thread with one flag — keep map pan and zoom buttery under huge fleets.

Quick start

Three lines to smooth motion.

Pick an adapter, hand the tracker your position stream, and start the loop. Everything else has production-grade defaults.

Tip: set renderLagMs ≈ feed period so the engine always has two points to interpolate between. The default is 1000.

vehicles.tsts
import { Tracker } from '@kinesisjs/core';
import { OpenLayersAdapter } from '@kinesisjs/openlayers';

const tracker = new Tracker({
  adapter: new OpenLayersAdapter(map),
  interpolation: 'adaptive',
});

tracker.start();

ws.onmessage = (e) => tracker.ingest(JSON.parse(e.data));
live-map.component.tsts
import { Component, inject } from '@angular/core';
import { KinesisMapDirective } from '@kinesisjs/angular';

@Component({
  standalone: true,
  imports: [KinesisMapDirective],
  template: `
    <div kinesisMap
         [positions]="positions"
         [interpolation]="'adaptive'"></div>`,
})
export class LiveMapComponent {
  positions = inject(FeedService).positions; // Signal<Position[]>
}
custom-interpolator.tsts
import { Tracker, type TrailPoint } from '@kinesisjs/core';

const tracker = new Tracker({
  adapter,
  interpolation: {
    compute(from: TrailPoint, to: TrailPoint, ratio: number): TrailPoint {
      // snap to your own road graph, predict, dead-reckon…
      return { ...to, lng: from.lng + (to.lng - from.lng) * ratio,
                       lat: from.lat + (to.lat - from.lat) * ratio };
    },
  },
});

tracker.start();
Interpolation modes

Pick a curve — or let it pick for you.

Five built-in strategies plus an adaptive meta-mode that reads each vehicle's feed period and chooses at runtime.

linear

Straight-line lerp between the two latest points. The default — right for most feeds.

cubic

Smoothstep easing — softer acceleration into and out of each segment.

geodesic

Great-circle arc across the globe. For ships, aircraft and long distances.

smooth

3-point centripetal Catmull-Rom. Rounds the path through turns once a third ping lands.

autoadaptive

Reads feed period per vehicle → snap, lerp, or fade. Zero manual tuning.

Architecture

Three layers, one responsibility each.

Layer 3 · Wrapper
Framework bindings

Reactive inputs (Signal / Observable / Hook) and lifecycle wired to the framework's teardown.

@kinesisjs/angular · react* · vue*
Layer 2 · Adapter
Map feature lifecycle

Create, update and remove features; styling, trails and viewport. One small adapter per map library.

@kinesisjs/openlayers · @kinesisjs/leaflet
Layer 1 · Core
The interpolation engine

Clock (rAF · 60fps), Interpolator, Sweeper lifecycle, typed EventBus and math utils. Zero deps.

@kinesisjs/core
ingest(positions)SlotBufferClock · 60fps tick(hl)interpolateadapter.updatePosition()
Packages

Install only what your map needs.

A tiny core plus opt-in adapters and wrappers. Every package ships ESM + CJS and full type definitions.

@kinesisjs/core

The framework-agnostic interpolation engine: clock, modes, lifecycle, events.

<5 KB min+gzip0 deps
$ npm i @kinesisjs/core
@kinesisjs/openlayers

OpenLayers adapter with vehicle styling, fading trails and gap visualization.

<3 KBpeer ol
$ npm i @kinesisjs/openlayers
@kinesisjs/angular

Standalone kinesisMap directive — Signals/RxJS in, auto-teardown out.

<2 KBpeer @angular/core
$ npm i @kinesisjs/angular
@kinesisjs/leaflet

Leaflet adapter with heading-aware markers that co-exist with your own layers.

~2 KBpeer leaflet
$ npm i @kinesisjs/leaflet
@kinesisjs/route-aware

OSRM-backed road-snapping CustomInterpolator with an LRU cache.

0 depsdrop-in
$ npm i @kinesisjs/route-aware
Benchmarked, not promised

Built for a screen that stays open all shift.

0.15ms
Tick @ 1000 vehicles
60fps
rAF-synced loop
~1%
Of the frame budget
1000+
Vehicles, one thread

Read it all back live with getStats() — p50/p95/p99 tick times, ingest rate, dropped ticks and a memory breakdown. Need more headroom? Move the loop off-thread with Web Worker mode (v0.2).

How it compares

One job, done where others stop.

CapabilityKinesis.jsleaflet-realtimeMovingMarkerraw setCoords
60fps interpolationpartialpartial
Map-library agnosticLeaflet onlyLeaflet only
Adaptive period handling
Bounded memory profilepartial
Multi-state lifecycle
Error-as-event
TypeScript-firsttypes
Roadmap

Shipping in the open.

v0.1.x
● shipping now
  • Core engine + adaptive
  • OpenLayers & Leaflet adapters
  • Angular wrapper
  • route-aware (OSRM)
v0.2
next
  • Web Worker mode
  • Playout polish
  • More events
v0.3
planned
  • React wrapper
  • Vue wrapper
  • MapLibre adapter
v0.4
planned
  • @kinesisjs/predict
  • Dead reckoning
  • Kalman filtering
Get started

Stop teleporting your fleet.

Drop in the tracker, hand it your stream, and watch the jumps turn into motion. Five kilobytes, zero dependencies.