UNPKG

s2maps-gpu

Version:

S2 Maps GPU - An open source, high-performance, and GPU-accelerated map engine for rendering large-scale, interactive maps.

584 lines (583 loc) β€’ 25.2 kB
import type { AnimationDirections } from './ui/camera/animator.js'; import type { MapOptions } from './ui/s2mapUI.js'; import type { MarkerDefinition } from './workers/source/markerSource.js'; import type S2MapUI from './ui/s2mapUI.js'; import type { LayerStyle, StyleDefinition, View } from './style/style.spec.js'; import type { MapGLMessage, SourceWorkerMessage, TileWorkerMessage } from './workers/worker.spec.js'; export type * from './ui/s2mapUI.js'; export type { MarkerDefinition } from './workers/source/markerSource.js'; export type { AnimationDirections } from './ui/camera/animator.js'; export type { UserTouchEvent } from './ui/camera/dragPan.js'; /** * Color blind states * - 0: None * - 1: Protanopia * - 2: Deuteranopia * - 3: Tritanopia * - 4: Greyscale */ export type ColorMode = 0 | 1 | 2 | 3 | 4; declare global { /** a global object exposed to the window */ interface Window { S2Map: typeof S2Map; } } /** * # The S2 Map GPU Engine 🌎 πŸ—ΊοΈ * * ## Description * * Both an **S2** and **WM** Projection Map Engine Powered by `WebGL1`, `WebGL2`, and `WebGPU`. * * ### Basic JS/TS example: * Note that the most important components to build a map are the {@link MapOptions} and the {@link StyleDefinition}. * ```ts * import { S2Map } from 's2maps-gpu'; // or you can access it via the global `window.S2Map` * import type { MapOptions, StyleDefinition } from 's2maps-gpu'; * * // build a style guide of sources to fetch and layers to render * const style: StyleDefinition = { ... }; * // setup options for the map * const options: MapOptions = { * container: 'map', // the ID of the HTML element to render the map into * // You can reference a canvas instead of a container: * // canvas: userPulledCanvasElement * style, * }; * // Build the map * const map = new S2Map(options); * ``` * * ### HTML Example * ```html * <!DOCTYPE html> * <html lang="en"> * <head> * <meta charset="utf-8" /> * <title>Display a map</title> * <meta name="viewport" content="initial-scale=1,width=device-width" /> * <!-- import s2maps-gpu. BE SURE TO CHECK AND UPDATE TO LATEST VERSION --> * <script src="https://opens2.com/s2maps-gpu/v0.18.0/s2maps-gpu.min.js" crossorigin="anonymous"></script> * <link rel="stylesheet" href="https://opens2.com/s2maps-gpu/v0.18.0/s2maps-gpu.min.css" /> * </head> * <body> * <div id="map"></div> * <script> * // grab container div * const container = document.getElementById('map'); * // setup map style * const style = { ... }; * // create the map * const map = new S2Map({ style, container }); * </script> * </body> * </html> * ``` * * ## Events * - `ready`: fired when the map is ready to be interacted with / make API calls. Ships this map {@link S2Map} * - `mouseleave`: fired when the mouse leaves the map. Ships {@link MouseLeaveMessage} * - `mouseenter`: fired when the mouse enters the map. Ships {@link MouseEnterMessage} * - `click`: fired when the user clicks on the map. Ships {@link MouseClickMessage} * - `view`: fired when the map view changes. Ships {@link ViewMessage} * - `screenshot`: fired as a result of a screenshot that was requested. Ships a `Uint8ClampedArray` * - `rendered`: fired when the map is fully rendered. * - `delete`: fired to ping that the map is deleting itself. * * ## API * - {@link S2Map.setDarkMode}: Update the state of the map's UI mode. True for dark-mode, false for light-mode * - {@link S2Map.getContainer}: Get the HTML element that the map is rendered into * - {@link S2Map.getCanvasContainer}: Get the HTML element that the map's canvas is rendered into * - {@link S2Map.getContainerDimensions}: Get the dimensions of the map's container as a `[width, height]` tuple * - {@link S2Map.setStyle}: Set a new style, replacing the current one if it exists * - {@link S2Map.updateStyle}: Update the map's current style with new attributes, by checking for changes and updating accordingly * - {@link S2Map.setMoveState}: Update the users ability to move the map around or not. * - {@link S2Map.setZoomState}: Update the users ability to zoom the map in and out or not. * - {@link S2Map.getView}: Get the current projector's view of the world * - {@link S2Map.jumpTo}: Jump to a specific location's longitude, latitude, and optionally zoom * - {@link S2Map.easeTo}: Use an easing function to travel to a specific location's longitude, latitude, and optionally zoom * - {@link S2Map.flyTo}: Use an easing function to fly to a specific location's longitude, latitude, and optionally zoom * - {@link S2Map.addSource}: Add a new source to the map. Sources are references to data and how to fetch it. * - {@link S2Map.updateSource}: Update a source already added to the map and control the method the map updates the source * - {@link S2Map.resetSource}: Reset a source's data already added to the map and control the method the map updates the source * - {@link S2Map.deleteSource}: Delete a source's data from the map * - {@link S2Map.addLayer}: Add a new style layer to the map * - {@link S2Map.updateLayer}: Update the an existing style layer in a map given the layer's name or index * - {@link S2Map.deleteLayer}: Delete an existing style layer in a map given the layer's name or index * - {@link S2Map.reorderLayers}: Reorder layers in the map. * - {@link S2Map.addMarker}: Add new marker(s) to the map * - {@link S2Map.removeMarker}: Delete a marker or collection of markers from the map * - {@link S2Map.screenshot}: Take a screenshot of the current state of the map. Returns the screenshot as a `Uint8ClampedArray` * - {@link S2Map.awaitFullyRendered}: Async function to wait for the map to have all source and layer data rendered to the screen * - {@link S2Map.delete}: Delete the map instance and cleanup all it's resources * * ## Future API * - `getBounds` & `setBounds` * - `setProjection` & `getProjection` * - `getStyle` * * ## Converters * - MapLibre Map Options Converter: See {@link plugins.convertMaplibreOptions} * - MapLibre Style Converter: See {@link plugins.convertMaplibreStyle} * * ## Plugins * - Sync map movements between multiple maps: See {@link plugins.syncMove} * * ## Frameworks * - React: See {@link plugins.ReactS2MapGPU} * - Vue: See {@link plugins.VueS2MapGPU} */ export default class S2Map extends EventTarget { #private; bearing: number; pitch: number; colorMode: ColorMode; map?: S2MapUI; hash: boolean; offscreen?: Worker; id: string; isNative: boolean; isReady: boolean; /** @param options - map options */ constructor(options?: MapOptions); /** * Add an event listener overriding the original * @param type - type of event called * @param listener - event listener * @param options - event listener options */ addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; /** * Inject data into the map * Used by the WorkerPool. * Anytime a Source worker or Tile Worker has data to inject into the map, * it will call this function. * @param data - The data to inject * @internal */ injectData(data: SourceWorkerMessage | TileWorkerMessage): void; /** * Used by the MapUI either from a thread or directly. to either * send messages to Source/Tile Workers or to the user. * @param message - The message to process * @internal */ onMessage(message: MessageEvent<MapGLMessage>): void; /** * Internal function to handle compass update. Expands upon camera compass update * @param bearing - compass bearing * @param pitch - compass pitch * @internal */ _updateCompass(bearing: number, pitch: number): void; /** * Update the state of the map's UI mode. * * ### Example * ```ts * import { S2Map } from 's2maps-gpu'; // or you can access it via the global `window.S2Map` * import type { MapOptions } from 's2maps-gpu'; * * const options: MapOptions = { ..., darkMode: false }; * const map = new S2Map(options); * // do something with the map * map.setDarkMode(true); * ``` * @param state - which UI mode to set the map to. `true` for dark-mode, `false` for light-mode */ setDarkMode(state?: boolean): void; /** * Get the HTML element that the map is rendered into * @returns The HTML element */ getContainer(): HTMLElement | undefined; /** * Get the HTML element that the map's canvas is rendered into * @returns The HTML element */ getCanvasContainer(): HTMLElement; /** * Get the dimensions of the map's container * @returns The dimensions of the map's container */ getContainerDimensions(): null | [width: number, height: number]; /** * Set a new style, replacing the current one if it exists * * ### Example * ```ts * import { S2Map } from 's2maps-gpu'; // or you can access it via the global `window.S2Map` * import type { MapOptions, StyleDefinition } from 's2maps-gpu'; * * const options: MapOptions = { ... }; * const map = new S2Map(options); * // setup and set a new style * const style: StyleDefinition = { ... }; * await map.setStyle(style); * ``` * @param style - The user defined style of how data should be rendered * @param ignorePosition - if set to true, don't update the map's position to the style's view guide [Default=`true`] */ setStyle(style: StyleDefinition, ignorePosition?: boolean): Promise<void>; /** * Update the map's current style with new attributes, by checking for changes and updating accordingly * * ### Example * ```ts * import { S2Map } from 's2maps-gpu'; // or you can access it via the global `window.S2Map` * import type { MapOptions, StyleDefinition } from 's2maps-gpu'; * * const options: MapOptions = { ..., style: { ... } }; * const map = new S2Map(options); * // Update the style with new attributes * const newStyle: StyleDefinition = { ... }; * map.updateStyle(newStyle); * ``` * @param style - The new style to update the old style with */ updateStyle(style: StyleDefinition): void; /** * Update the users ability to move the map around or not. * * ### Example * ```ts * import { S2Map } from 's2maps-gpu'; // or you can access it via the global `window.S2Map` * import type { MapOptions } from 's2maps-gpu'; * * const options: MapOptions = { ..., canMove: false }; * const map = new S2Map(options); * // Update the move state so the user can move around * const screen = map.setMoveState(true); * ``` * @param state - Sets the move state. If `true`, the user can move the map. */ setMoveState(state: boolean): void; /** * Update the users ability to zoom the map in and out or not. * * ### Example * ```ts * import { S2Map } from 's2maps-gpu'; // or you can access it via the global `window.S2Map` * import type { MapOptions } from 's2maps-gpu'; * * const options: MapOptions = { ..., canZoom: false }; * const map = new S2Map(options); * // Update the zoom state so the user can update the zoom position * const screen = map.setZoomState(true); * ``` * @param state - Sets the zoom state. If `true`, the user can zoom the map in and out. */ setZoomState(state: boolean): void; /** * Get the current projector's view of the world * * ### Example * ```ts * import { S2Map } from 's2maps-gpu'; // or you can access it via the global `window.S2Map` * import type { MapOptions, View } from 's2maps-gpu'; * * const options: MapOptions = { ..., view: { lon: 0, lat: 0, zoom: 0 } }; * const map = new S2Map(options); * // Get a filled in view object * const view: Required<View> = await map.getView(); * ``` * @returns A filled in {@link View} object */ getView(): Promise<Required<View>>; /** * Jump to a specific location's longitude, latitude, and optionally zoom, bearing, and pitch. * Takes a {@link View} object as an input. * * NOTE: If either the `lon` or `lat` are not set, it will assume the map's current position * * ### Example * ```ts * import { S2Map } from 's2maps-gpu'; // or you can access it via the global `window.S2Map` * import type { MapOptions } from 's2maps-gpu'; * * const options: MapOptions = { ..., view: { lon: 0, lat: 0, zoom: 0 } }; * const map = new S2Map(options); * // wait for map to load, then jump to a specific location * await map.awaitFullLoaded(); * map.jumpTo({ lon: -120, lat: 60, zoom: 7 }); * ``` * @param view - The view to jump to */ jumpTo(view: View): void; /** * Use an easing function to travel to a specific location's longitude, latitude, and optionally zoom * * ### Example * ```ts * import { S2Map } from 's2maps-gpu'; // or you can access it via the global `window.S2Map` * import type { MapOptions } from 's2maps-gpu'; * * const options: MapOptions = { ..., view: { lon: 0, lat: 0, zoom: 0 } }; * const map = new S2Map(options); * // wait for map to load, then jump to a specific location * await map.awaitFullLoaded(); * map.easeTo(-120, 60, 7); * ``` * @param directions - animation guide for travel directions, speed, and easing */ easeTo(directions?: AnimationDirections): void; /** * Use an easing function to fly to a specific location's longitude, latitude, and optionally zoom * * ### Example * ```ts * import { S2Map } from 's2maps-gpu'; // or you can access it via the global `window.S2Map` * import type { MapOptions } from 's2maps-gpu'; * * const options: MapOptions = { ..., view: { lon: 0, lat: 0, zoom: 0 } }; * const map = new S2Map(options); * // wait for map to load, then jump to a specific location * await map.awaitFullLoaded(); * map.flyTo(-120, 60, 7); * ``` * @param directions - animation guide for travel directions, speed, and easing */ flyTo(directions?: AnimationDirections): void; /** * Add a new source to the map. Sources are references to data and how to fetch it. * * ### Example * ```ts * import { S2Map } from 's2maps-gpu'; // or you can access it via the global `window.S2Map` * import type { MapOptions } from 's2maps-gpu'; * * const options: MapOptions = { ... }; * const map = new S2Map(options); * // Add a new source to the map * map.addSource('TheFreakinMoon', 'http://yup-im-the-moon.com/'); * ``` * @param sourceName - Name of the source * @param href - the location of the source data */ addSource(sourceName: string, href: string): void; /** * Update a source already added to the map and control the method the map updates the source * * ### Example * ```ts * import { S2Map } from 's2maps-gpu'; // or you can access it via the global `window.S2Map` * import type { MapOptions } from 's2maps-gpu'; * * const options: MapOptions = { ... }; * const map = new S2Map(options); * // Add a new source to the map * map.addSource('TheFreakinMoon', 'http://yup-im-the-moon.com/'); * // change the location of the moon * map.updateSource('TheFreakinMoon', 'http://now-im-the-moon.com/', false, true); * ``` * @param sourceName - Name of the source * @param href - the new location of the source * @param keepCache - Whether to keep the cache or not. don't delete any tiles, request replacements for all (for s2json since it's locally cached and fast) * @param awaitReplace - Whether to await the replacement of tiles or not. to avoid flickering (i.e. adding/removing markers), we can wait for an update (from source+tile workers) on how the tile should look */ updateSource(sourceName: string, href: string, keepCache?: boolean, awaitReplace?: boolean): void; /** * Reset a source's data already added to the map and control the method the map updates the source * * ### Example * ```ts * import { S2Map } from 's2maps-gpu'; // or you can access it via the global `window.S2Map` * import type { MapOptions } from 's2maps-gpu'; * * const options: MapOptions = { ... }; * const map = new S2Map(options); * // Add a new source to the map * map.addSource('TheFreakinMoon', 'http://yup-im-the-moon.com/'); * // change the location of the moon * map.resetSource(['TheFreakinMoon'], false, true); * ``` * @param sourceNames - Array of [sourceName, href]. Href is optional but if provided, the source href will be updated * @param keepCache - Whether to keep the cache or not. don't delete any tiles, request replacements for all (for s2json since it's locally cached and fast) * @param awaitReplace - Whether to await the replacement of tiles or not. to avoid flickering (i.e. adding/removing markers), we can wait for an update (from source+tile workers) on how the tile should look */ resetSource(sourceNames: Array<[sourceName: string, href: string | undefined]>, keepCache?: boolean, awaitReplace?: boolean): void; /** * Delete a source's data from the map * * ### Example * ```ts * import { S2Map } from 's2maps-gpu'; // or you can access it via the global `window.S2Map` * import type { MapOptions } from 's2maps-gpu'; * * const options: MapOptions = { ... }; * const map = new S2Map(options); * // Add a new source to the map * map.addSource('TheFreakinMoon', 'http://yup-im-the-moon.com/'); * // Do stuff ... * * // we are done rendering the moon * map.deleteSource(['TheFreakinMoon', 'anotherSourceWeDontWantAnymore']); * ``` * @param sourceNames - A single sourceName or an array of source names */ deleteSource(sourceNames: string | string[]): void; /** * Add a new style layer to the map * - If the nameIndex is a string, it will search through the existing layers for the layer with that name and add the layer at said index * - If the nameIndex is a number, it will add the layer at that index in the style.layers array. * - If no nameIndex is provided, it will add the layer at the end * * ### Example * ```ts * import { S2Map } from 's2maps-gpu'; // or you can access it via the global `window.S2Map` * import type { MapOptions } from 's2maps-gpu'; * * const options: MapOptions = { ... }; * const map = new S2Map(options); * // Add a new style layer to the map * map.addLayer({ source: 'world', type: 'fill', color: 'red', ... }); * ``` * @param layer - The style layer to add * @param nameIndex - The index to add the layer at */ addLayer(layer: LayerStyle, nameIndex?: number | string): void; /** * Update the an existing style layer in a map given the layer's name or index * - If the nameIndex is a string, it will search through the existing layers for the layer with that name and update the layer at said index * - If the nameIndex is a number, it will use the layer at that index in the style.layers array. * * ### Example * ```ts * import { S2Map } from 's2maps-gpu'; // or you can access it via the global `window.S2Map` * import type { MapOptions } from 's2maps-gpu'; * * const options: MapOptions = { ... }; * const map = new S2Map(options); * // Update the style layer * map.updateLayer({ source: 'world', type: 'fill', color: 'red', ... }, 12); * ``` * @param layer - The style layer to update/replace the old layer with * @param nameIndex - The index/name of the style layer to update * @param fullUpdate - If true, force a full re-render of the layer. Recommended to keep true unless you know what you're doing */ updateLayer(layer: LayerStyle, nameIndex: number | string, fullUpdate?: boolean): void; /** * Delete an existing style layer in a map given the layer's name or index * - If the nameIndex is a string, it will search through the existing layers for the layer with that name and update the layer at said index * - If the nameIndex is a number, it will use the layer at that index in the style.layers array. * * ### Example * ```ts * import { S2Map } from 's2maps-gpu'; // or you can access it via the global `window.S2Map` * import type { MapOptions } from 's2maps-gpu'; * * const options: MapOptions = { ... }; * const map = new S2Map(options); * // Delete an existing layer * map.updateLayer(12); * ``` * @param nameIndex - The index/name of the style layer to delete */ deleteLayer(nameIndex: number | string): void; /** * Reorder layers in the map. * - The key is the index of the layer to move * - The value is the index to move the layer to * * ### Example * ```ts * import { S2Map } from 's2maps-gpu'; // or you can access it via the global `window.S2Map` * import type { MapOptions } from 's2maps-gpu'; * * const options: MapOptions = { ... }; * const map = new S2Map(options); * // Reorder layers * map.reorderLayers({ 0: 1, 1: 0 }); * ``` * @param layerChanges - The guide of how to reorder the layers */ reorderLayers(layerChanges: Record<number, number>): void; /** * Add new marker(s) to the map * - See {@link MarkerDefinition} to see the shape of a marker * * ### Example * ```ts * import { S2Map } from 's2maps-gpu'; // or you can access it via the global `window.S2Map` * import type { MapOptions } from 's2maps-gpu'; * * const options: MapOptions = { ... }; * const map = new S2Map(options); * // add a new marker * map.addMarker({ id: 22, lat: 0, lon: 0, html: '<div>hello</div>' }); * ``` * @param markers - A single marker or an array of markers * @param sourceName - The name of the source to add the marker(s) to. [Default: `"_markers"`] */ addMarker(markers: MarkerDefinition | MarkerDefinition[], sourceName?: string): void; /** * Delete a marker or collection of markers from the map * * ### Example * ```ts * import { S2Map } from 's2maps-gpu'; // or you can access it via the global `window.S2Map` * import type { MapOptions } from 's2maps-gpu'; * * const options: MapOptions = { ... }; * const map = new S2Map(options); * // add a new marker * map.removeMarker(22); * ``` * @param ids - A single marker id or an array of marker ids to delete * @param sourceName - The name of the source to remove the marker(s) from. [Default: `"_markers"`] */ removeMarker(ids: number | number[], sourceName?: string): void; /** * Take a screenshot of the current state of the map. Returns the screenshot as an `Uint8ClampedArray`. * * ### Example * ```ts * import { S2Map } from 's2maps-gpu'; // or you can access it via the global `window.S2Map` * import type { MapOptions } from 's2maps-gpu'; * * const options: MapOptions = { ... }; * const map = new S2Map(options); * // wait for the map to be full rendered * await map.awaitFullyRendered(); * // request the current screen * const screen = await map.screenshot(); * ``` * @returns An RGBA encoded `Uint8ClampedArray` that is of size `canvas.width` * `canvas.height` */ screenshot(): Promise<null | Uint8ClampedArray>; /** * Async function to wait for the map to have all source and layer data rendered to the screen * * Useful for ensuring the map is rendered before running tests, starting an animation, * making changes, etc. * * ### Example * ```ts * import { S2Map } from 's2maps-gpu'; // or you can access it via the global `window.S2Map` * import type { MapOptions } from 's2maps-gpu'; * * const options: MapOptions = { ... }; * const map = new S2Map(options); * // wait for the map to be full rendered before making future changes * await map.awaitFullyRendered(); * // do more stuff * ``` */ awaitFullyRendered(): Promise<void>; /** * Delete the map instance and cleanup all it's resources * * ### Example * ```ts * import { S2Map } from 's2maps-gpu'; // or you can access it via the global `window.S2Map` * import type { MapOptions } from 's2maps-gpu'; * * const options: MapOptions = { ... } * const map = new S2Map(options) * // do something with the map * map.delete() // cleanup * ``` */ delete(): void; }