diff --git a/CHANGELOG.md b/CHANGELOG.md index 48903bc..40a7ba5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Updates +## `0.1.2` (2025-10-31). + +Added TypeScript types, closing [PR #14](https://github.com/AR-js-org/locar.js/issues/14). + ## `0.1.1` (2025-10-11) Allow inline styling of the iOS permission dialogs for device orientation, as well as providing a more iOS-native style by default (PR #22). Thanks to [Luigi Mannoni](https://github.com/luigimannoni-smartify) for this. diff --git a/lib/types/locar.d.ts b/lib/types/locar.d.ts new file mode 100644 index 0000000..b0b6a1c --- /dev/null +++ b/lib/types/locar.d.ts @@ -0,0 +1,316 @@ +declare module "locar" { + import * as THREE from "three"; + + /** + * Generic, small event emitter that only stores a single handler per event name. + */ + export class EventEmitter { + protected eventHandlers: Record void>; + on(eventName: string, handler: (...args: any[]) => void): void; + emit(eventName: string, ...params: any[]): void; + } + + /** + * Spherical Mercator (EPSG:3857) projection used by `LocationBased`. + */ + export class SphMercProjection { + constructor(); + /** + * @returns [easting, northing] + */ + project(lon: number, lat: number): [number, number]; + /** + * @returns [lon, lat] + */ + unproject(projected: [number, number]): [number, number]; + getID(): "epsg:3857"; + } + + /** + * Options for GPS in `LocationBased`. + * Mirrored from `setGpsOptions(...)` + */ + export interface GpsOptions { + /** + * Meters the device must move to accept the next GPS reading. + */ + gpsMinDistance?: number; + /** + * Minimum accuracy in meters to accept a GPS reading. + */ + gpsMinAccuracy?: number; + } + + /** + * Optional logger object passed to `LocationBased` for debug. + */ + export interface ServerLogger { + /** + * Should send data to server. Implementation-specific in userland. + */ + sendData(endpoint: string, data: any): Promise | Response; + } + + /** + * Main location AR class. + */ + export class LocationBased extends EventEmitter { + readonly scene: THREE.Scene; + readonly camera: THREE.Camera; + + constructor( + scene: THREE.Scene, + camera: THREE.Camera, + options?: GpsOptions, + serverLogger?: ServerLogger | null, + ); + + /** + * Set the projection (must have `project(lon,lat): [x,y]`). + */ + setProjection(proj: { + project(lon: number, lat: number): [number, number]; + }): void; + + /** + * Update GPS options at runtime. + */ + setGpsOptions(options?: GpsOptions): void; + + /** + * Start real GPS (`navigator.geolocation.watchPosition`). + */ + startGps(): Promise | boolean; + + /** + * Stop real GPS. + */ + stopGps(): boolean; + + /** + * Send a fake GPS position. + */ + fakeGps(lon: number, lat: number, elev?: number | null, acc?: number): void; + + /** + * Convert lon/lat to world coordinates (needs initial position). + */ + lonLatToWorldCoords(lon: number, lat: number): [number, number]; + + /** + * Add a THREE object at lon/lat/(elev) and put in the scene. + */ + add( + object: THREE.Object3D, + lon: number, + lat: number, + elev?: number, + properties?: Record, + ): void; + + /** + * Set camera elevation (y). + */ + setElevation(elev: number): void; + + /** + * Events: + * - "gpsupdate": `{ position: GeolocationPosition, distMoved: number }`` + * - "gpserror": `GeolocationPositionError` + */ + on( + eventName: "gpsupdate", + handler: (data: { + position: GeolocationPosition; + distMoved: number; + }) => void, + ): void; + on( + eventName: "gpserror", + handler: (error: GeolocationPositionError) => void, + ): void; + on(eventName: string, handler: (...args: any[]) => void): void; + } + + /** + * Small webcam wrapper that creates a hidden `