61 lines
1.8 KiB
TypeScript
61 lines
1.8 KiB
TypeScript
import { TripsLayer } from '@deck.gl/geo-layers';
|
|
import type { Layer } from '@deck.gl/core';
|
|
import type { ProcessedTrack } from '../model/track.types';
|
|
import { getShipKindColor } from '../lib/adapters';
|
|
import { TRACK_REPLAY_LAYER_IDS } from './trackLayers';
|
|
import { DEPTH_DISABLED_PARAMS } from '../../../widgets/map3d/constants';
|
|
|
|
interface ReplayTrip {
|
|
vesselId: string;
|
|
path: [number, number][];
|
|
timestamps: number[];
|
|
color: [number, number, number, number];
|
|
}
|
|
|
|
function toReplayTrips(tracks: ProcessedTrack[]): ReplayTrip[] {
|
|
const out: ReplayTrip[] = [];
|
|
for (const track of tracks) {
|
|
if (!track.geometry.length || !track.timestampsMs.length) continue;
|
|
const baseTime = track.timestampsMs[0];
|
|
out.push({
|
|
vesselId: track.vesselId,
|
|
path: track.geometry,
|
|
timestamps: track.timestampsMs.map((ts) => ts - baseTime),
|
|
color: getShipKindColor(track.shipKindCode),
|
|
});
|
|
}
|
|
return out;
|
|
}
|
|
|
|
export function createReplayTrailLayer(options: {
|
|
tracks: ProcessedTrack[];
|
|
currentTime: number;
|
|
showTrail: boolean;
|
|
}): Layer | null {
|
|
const { tracks, currentTime, showTrail } = options;
|
|
if (!showTrail || tracks.length === 0) return null;
|
|
|
|
const trips = toReplayTrips(tracks);
|
|
if (trips.length === 0) return null;
|
|
|
|
const minBaseTime = Math.min(...tracks.map((track) => track.timestampsMs[0] || 0));
|
|
const relativeCurrentTime = Math.max(0, currentTime - minBaseTime);
|
|
|
|
return new TripsLayer<ReplayTrip>({
|
|
id: TRACK_REPLAY_LAYER_IDS.TRAIL,
|
|
data: trips,
|
|
getPath: (d) => d.path,
|
|
getTimestamps: (d) => d.timestamps,
|
|
getColor: (d) => d.color,
|
|
currentTime: relativeCurrentTime,
|
|
trailLength: 1000 * 60 * 60,
|
|
fadeTrail: true,
|
|
widthMinPixels: 2,
|
|
widthMaxPixels: 4,
|
|
capRounded: true,
|
|
jointRounded: true,
|
|
parameters: DEPTH_DISABLED_PARAMS,
|
|
pickable: false,
|
|
});
|
|
}
|