isard 1.9.0 → 1.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/README.md +9 -4
- package/dist/basemap/vectortiles/requests.d.ts +8 -1
- package/dist/basemap/vectortiles/requests.js +32 -4
- package/dist/basemap/vectortiles/requests.js.map +1 -1
- package/dist/basemap/vectortiles/vectors.d.ts +8 -1
- package/dist/basemap/vectortiles/vectors.js +26 -2
- package/dist/basemap/vectortiles/vectors.js.map +1 -1
- package/dist/basemap/vectortiles.d.ts +2 -1
- package/dist/basemap/vectortiles.js +3 -1
- package/dist/basemap/vectortiles.js.map +1 -1
- package/dist/basemap.worker.js +2 -2
- package/dist/basemap.worker.js.map +4 -4
- package/dist/bind/layers.js +3 -0
- package/dist/bind/layers.js.map +1 -1
- package/dist/data/tileset.d.ts +21 -0
- package/dist/data/tileset.js +101 -0
- package/dist/data/tileset.js.map +1 -0
- package/dist/decoder.worker.js +3 -3
- package/dist/decoder.worker.js.map +3 -3
- package/dist/engine-loader.d.ts +2 -2
- package/dist/engine-loader.js +9 -3
- package/dist/engine-loader.js.map +1 -1
- package/dist/isard_bg.wasm +0 -0
- package/dist/isard_core_bg.wasm +0 -0
- package/dist/isard_tess_bg.wasm +0 -0
- package/dist/layers/tiles3d.d.ts +5 -0
- package/dist/layers/tiles3d.js +15 -1
- package/dist/layers/tiles3d.js.map +1 -1
- package/dist/layers/vectors.d.ts +3 -0
- package/dist/layers/vectors.js +4 -0
- package/dist/layers/vectors.js.map +1 -1
- package/dist/map.d.ts +10 -0
- package/dist/map.js +23 -2
- package/dist/map.js.map +1 -1
- package/dist/react/VectorGeometry.d.ts +4 -0
- package/dist/react/VectorGeometry.js +6 -3
- package/dist/react/VectorGeometry.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.js.map +1 -1
- package/dist/ui/interaction.d.ts +4 -0
- package/dist/ui/interaction.js +53 -2
- package/dist/ui/interaction.js.map +1 -1
- package/dist/wasm/isard.d.ts +18 -1
- package/dist/wasm/isard.js +28 -2
- package/dist/wasm/isard_core.d.ts +13 -1
- package/dist/wasm/isard_core.js +20 -2
- package/dist/workers/basemap/protocol.d.ts +3 -0
- package/package.json +1 -1
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,0CAA0C","sourcesContent":["/** Public types of the `isard` package */\n\nimport type { TileGrid } from './basemap/grid.ts';\nimport type { DecoderUrls } from './decoding/decoders.ts';\nimport type { Feature, Ramp, Size } from './layers/features.ts';\nimport type { Layer } from './layers/layers.ts';\nimport type { AttributionOptions } from './ui/controls.ts';\nimport type { Camera, Engine } from './wasm/isard.js';\n\nexport type LonLat = [lon: number, lat: number];\nexport type Point = [x: number, y: number];\n\n/**\n * The named basemaps. OpenFreeMap's vector styles, OpenStreetMap data worldwide, their labels above the other layers:\n * `osm-positron` (light grey, quiet: data over it reads first), `osm-liberty` and `osm-bright` (in colour), `osm-dark`\n * (near black: bright data over it, a wind's particles, lights). The\n * Géoplateforme's (IGN, France): rasters (`ign-plan`, `ign-plan-grey`, `ign-ortho`, the aerial photographs) or vector\n * tiles with their labels (`ign-plan-vector`, `ign-plan-grey-vector`, the PLAN.IGN styles).\n */\nexport type BasemapName =\n | 'osm-positron'\n | 'osm-liberty'\n | 'osm-bright'\n | 'osm-dark'\n | 'ign-plan'\n | 'ign-plan-grey'\n | 'ign-ortho'\n | 'ign-plan-vector'\n | 'ign-plan-grey-vector'\n | 'none';\n\n/** A basemap by name (see `BasemapName`) */\nexport type Basemap = BasemapName;\n\n/**\n * The Earth's named terrain models. `'terrain-tiles'`: worldwide, the Terrain Tiles of AWS's open data registry\n * (SRTM, EU-DEM, GMTED… merged by Mapzen, 30 m in most places), the sea floor flattened at sea level. `'ign'`: France,\n * the IGN's RGE ALTI from the Géoplateforme (1 to 5 m), raised by the RAF20 geoid to heights above the ellipsoid.\n */\nexport type TerrainModel = 'terrain-tiles' | 'ign';\n\n/** How tiles encode their altitudes: `'float32'`, raw little-endian floats (`image/x-bil;bits=32`, an ArcGIS raw\n * grid); `'terrarium'`, the colors of a PNG, `R × 256 + G + B / 256 - 32768`; `'mapbox'`, those of Terrain-RGB,\n * `(R × 65536 + G × 256 + B) / 10 - 10000` */\nexport type TerrainEncoding = 'float32' | 'terrarium' | 'mapbox';\n\n/**\n * How tiles load and show. 'immediate' (default): everything visible loads, tiles show as soon as they arrive.\n * 'smooth': during flights the levels flown through are skipped, off-center tiles wait while the camera moves, tiles\n * fade in; fewer downloads, for slow networks or GPUs.\n */\nexport type LoadingMode = 'immediate' | 'smooth';\n\n/** 'globe': a sphere at low zoom, blending into Web Mercator between zooms 5 and 7, up to three levels later under a\n * tilted camera (it sees much farther than its center: the horizon stays curved) */\nexport type Projection = 'globe' | 'mercator';\n\n/** A body to draw the map on, other than the named ones (`CelestialBody`) */\nexport interface BodyOptions {\n /** Equatorial radius, metres */\n radius: number;\n /** Flattening of its ellipsoid, 0 for a sphere (default 0) */\n flattening?: number;\n /** An atmosphere: its halo around the globe, true for the Earth's light blue, or a CSS color (its alpha the\n * halo's strength) (default false) */\n atmosphere?: boolean | string;\n /** Color of the globe where no tile covers it (past the Web Mercator latitudes, 85°), a CSS color (default\n * `#808080`) */\n color?: string;\n /** Lowest and highest altitudes of its ground, metres around the ellipsoid: what its relief may raise into view\n * (default ±1 % of the radius) */\n relief?: [lowest: number, highest: number];\n}\n\n/**\n * The body the map is drawn on: 'earth' (WGS 84, the default), 'moon' (a sphere of 1 737 400 m, no atmosphere),\n * 'mars' (a sphere of 3 396 190 m, its equatorial radius, a thin dusty halo; planetocentric latitudes) or another\n * one. Zoom levels keep their meaning on screen (the Web Mercator tile pyramid), their metres follow the body:\n * altitudes, relief, buildings, 3D Tiles. Off the Earth, the map has none of the Earth's defaults: no basemap, no\n * credits, and space for its background; the Moon and Mars have NASA's relief for `terrain: true`.\n */\nexport type CelestialBody = 'earth' | 'moon' | 'mars' | BodyOptions;\n\nexport interface GeoMapOptions extends Partial<Camera> {\n /** The body the map is drawn on (default 'earth'); set at creation */\n body?: CelestialBody;\n /** Default 'globe' */\n projection?: Projection;\n /** Default 'immediate' */\n loading?: LoadingMode;\n /** The basemap (default 'osm-positron'; 'none' off the Earth) */\n basemap?: Basemap;\n /** Opacity of the IGN hillshade over the basemap (France, Géoplateforme), 0 for none (default 0) */\n hillshade?: number;\n /** Color behind the map (sky of tilted flat views), a CSS color (default `#f2f2f0`; black off the Earth) */\n background?: string;\n /** Space behind the globe: stars and atmosphere halo, fading out as the globe turns flat (default true) */\n sky?: boolean;\n /** The sun casting the shadows of buildings, trees, models and the relief (`setSun`); none by default */\n sun?: SunOptions;\n /** Relief under the basemap: true for the body's terrain model (on the Earth the worldwide Terrain Tiles; NASA's on\n * the Moon and Mars: LOLA, MOLA), one of the Earth's models by name (`'ign'`: France, RGE ALTI), or its options\n * (default false; on another body, its `url` is required). Network layers are draped on it */\n terrain?: boolean | TerrainModel | TerrainOptions;\n minZoom?: number;\n maxZoom?: number;\n /** Highest pitch, degrees, up to 85 (default 70) */\n maxPitch?: number;\n /** Sky over the plane, seen when the camera is tilted towards the horizon, and the fog the ground fades into\n * (MapLibre's `setSky`); default none: the background color */\n atmosphere?: AtmosphereOptions;\n /** Mouse, touch and keyboard controls (default true) */\n interactive?: boolean;\n /** Keyboard controls once the map has the focus (it is reached with Tab): arrows pan, Shift + arrows rotate and\n * tilt, + and - zoom (Shift: two levels), 0 faces north and levels the view (default true; none when not\n * `interactive`) */\n keyboard?: boolean;\n /** Accessible name of the map, read by screen readers (default 'Map') */\n ariaLabel?: string;\n /** A preset of map options (`IGN_PRESETS`: `'ign'`, `'ign-3d'`, `'ign-ortho-3d'`), the other options over it */\n preset?: 'ign' | 'ign-3d' | 'ign-ortho-3d';\n /** The folder isard's files are served from (its engines, `isard_bg.wasm`, `isard_core_bg.wasm`,\n * `isard_points_bg.wasm`, `isard_tess_bg.wasm`, `isard_grid_bg.wasm`, and its workers, `decoder.worker.js`, `basemap.worker.js`): one option for a bundler that\n * moves them, the `…Url` options below for each one. `isard/vite` sets it for the whole page; default next to the\n * module */\n assetsUrl?: string | URL;\n /** Where to load the engine with 3D Tiles from (`isard_bg.wasm`), when a bundler does not resolve the default URL.\n * Given without `coreWasmUrl`, maps load this engine from the start */\n wasmUrl?: string | URL;\n /** Where to load the engine without 3D Tiles from (`isard_core_bg.wasm`, a third smaller), when a bundler does not\n * resolve the default URL. Maps load it first, and the engine with 3D Tiles (`wasmUrl`) for their first 3D Tiles\n * layer only */\n coreWasmUrl?: string | URL;\n /** Where the decoding workers load the point cloud module from (`isard_points_bg.wasm`, the LAZ decoder of COPC),\n * when a bundler does not resolve the default URL. Loaded with the first point cloud only */\n pointsWasmUrl?: string | URL;\n /** Where the basemap workers load the tessellation module from (`isard_tess_bg.wasm`: the vector tiles drawn as\n * geometry, `vectorTiles().vectors()`, made ready for the GPU off the main thread), when a bundler does not resolve\n * the default URL. Loaded with the first tile of geometry; without it, the main thread does that work */\n tessWasmUrl?: string | URL;\n /** Where the workers load the grid module from (`isard_grid_bg.wasm`: GRIB2 and NetCDF files read by\n * `map.readGrids`), when a bundler does not resolve the default URL. Loaded with the first file */\n gridWasmUrl?: string | URL;\n /** Load the engine with 3D Tiles from the start (default false: it is loaded when the first 3D Tiles layer or glTF\n * model is added, the map then moving its camera and layers onto it, a stall of about a frame or two). For a map that shows 3D Tiles\n * at once: one engine downloaded instead of two. `'preload'`: the map starts on the engine without 3D Tiles and\n * downloads and compiles the other once idle, without running it: its first 3D Tiles layer does not wait for the\n * download (for a map that will show 3D Tiles later, on demand) */\n tiles3d?: boolean | 'preload';\n /** Where to load the vector basemap worker from, when a bundler does not resolve the default URL */\n basemapWorkerUrl?: string | URL;\n /** Texture size of the vector basemap's tiles, pixels (default 512: lines and edges sharp at every zoom on a screen\n * of pixel ratio 1). 256: a quarter of the drawing in the workers, of the uploads and of the GPU memory, for lines\n * and edges a little softer between two zoom levels (the tiles are shown 181 to 362 CSS pixels wide) */\n basemapTileSize?: number;\n /** Glyphs of the symbol layers: a URL with `{fontstack}` and `{range}` (MapLibre's glyph format; default\n * OpenFreeMap's fonts, Noto Sans). A vector basemap's labels take the glyphs of its style */\n glyphs?: string;\n /** Workers decoding 3D Tiles off the main thread: a count, or false to decode on the main thread (default: cores - 1,\n * 1 to 4). False (or 0) also decodes the PNG relief and reprojects the equirectangular rasters on the main thread,\n * else done by the vector basemap's workers */\n workers?: number | false;\n /** Where to load the decoding worker from, when a bundler does not resolve the default URL */\n workerUrl?: string | URL;\n /** Folders of the Draco and Basis Universal decoders, loaded by the workers on first use (default: the official\n * builds on gstatic.com and jsDelivr; self-host them for offline or locked-down networks). They run through\n * `new Function`: a Content Security Policy needs `'unsafe-eval'` (see `DecoderUrls`) */\n decoders?: Partial<DecoderUrls>;\n /** Credits at the bottom right: false for none, or its options (default true: the credits of the basemap,\n * hillshade and relief in use, compact on maps narrower than 640 px) */\n attributionControl?: boolean | AttributionOptions;\n}\n\nexport interface TerrainOptions {\n /** One of the Earth's named models (default `'terrain-tiles'` on the Earth); unused with a `url` */\n model?: TerrainModel;\n /** Altitudes of 256 × 256 tiles in `encoding`: a WMS GetMap URL with {bbox} (EPSG:3857 on the Earth, the body's\n * Mercator metres elsewhere: the sphere of its radius), a tile URL with {z}, {x} and {y}, or an ArcGIS image service\n * (a URL ending in `/ImageServer`), asked for raw altitudes in the body's Mercator (default: the `model`'s; on the\n * Moon and Mars, NASA's Trek LOLA and MOLA models) */\n url?: string;\n /** How the tiles of `url` encode their altitudes (default `'float32'`); `'terrarium'` and `'mapbox'` take a URL with\n * {z}, {x} and {y} */\n encoding?: TerrainEncoding;\n /** Vertical exaggeration, 1 for the true relief (default 1) */\n exaggeration?: number;\n /** Finest level of the relief, up to 15 (default 15; 14 for the Terrain Tiles, 8 for the Moon's and Mars's models). It\n * starts at level 6 on the Earth, coarser on bodies of a larger relief for their size (3 on the Moon and Mars) */\n maxZoom?: number;\n /** Altitudes over mainland France raised by the height of the RAF20 geoid (the French one, 0 away from France), to\n * heights above the ellipsoid (those of 3D Tiles); false keeps the altitudes as served (NGF-IGN69 for the IGN's)\n * (default true for the `'ign'` model, false otherwise) */\n geoid?: boolean;\n}\n\n/** Sky, horizon and fog over the plane, with the names and meanings of MapLibre's `setSky` */\nexport interface AtmosphereOptions {\n /** A CSS color (default `#9cc7ec`) */\n skyColor?: string;\n /** (default `#e8f1f8`) */\n horizonColor?: string;\n /** (default `#f2f5f8`) */\n fogColor?: string;\n /** Blend from the horizon to the sky color, share of the field of view above the horizon, 0-1 (default 0.6) */\n skyHorizonBlend?: number;\n /** Blend from the horizon to the fog color below the horizon, 0-1 (default 0.7) */\n horizonFogBlend?: number;\n /** Share of the distance to the far plane over which the ground fades into the fog, 0-1 (default 0.4) */\n fogGroundBlend?: number;\n}\n\n/** The sun casting shadows (`GeoMap.setSun`): where it stands, by date or by hand, and how dark its shadows are */\nexport interface SunOptions {\n /** The time: the sun where it stands then over the map's center (default now, unless `azimuth` and `altitude`) */\n date?: Date;\n /** Degrees clockwise from north, with `altitude`: the sun placed by hand */\n azimuth?: number;\n /** Degrees above the horizon; at or under it, no shadows */\n altitude?: number;\n /** How dark the shadows are, 0 to 1 (default 0.35) */\n opacity?: number;\n /** How dark the night is, 0 to 1: the scene tinted in its blue, the windows of the buildings and the streets of\n * `vectors()` lit, the labels light on dark. By default from the sun's altitude: falling from 6° above the horizon\n * to 6° under it */\n night?: number;\n}\n\n/** What can be seen from a point (`GeoMap.setViewshed`); with several observers, the colors, the opacity and the\n * cone's color are the first one's */\nexport interface ViewshedOptions {\n /** The observer */\n position: LonLat;\n /** Metres above the ground (default 1.7, eye level) */\n height?: number;\n /** Metres around the observer that are tinted (default 1000) */\n range?: number;\n /** A CSS color for what is seen (default `#2f9e44`) */\n visibleColor?: string;\n /** A CSS color for what is hidden (default `#e03131`) */\n hiddenColor?: string;\n /** How strongly the colors tint the scene, multiplied into it so that its textures and shading stay, 0-1 (default\n * 0.7) */\n opacity?: number;\n /** A CSS color for the cone drawn in 3D (one way only): its fan through the axis, at the eye's height and tilted\n * with it, from the eye to the range; solid where nothing hides it, faint behind the scene; none by default */\n coneColor?: string;\n /** To look one way only (a camera, a lookout), degrees clockwise from north; all around without it */\n direction?: number;\n /** Degrees above the horizon the cone looks, negative below (default 0) */\n tilt?: number;\n /** Angle of view across, degrees (default 60) */\n fov?: number;\n /** Angle of view up and down, degrees (default 40) */\n verticalFov?: number;\n}\n\n/** An eye at street level (`GeoMap.setFirstPerson`) */\nexport interface FirstPersonView {\n /** Where it stands */\n lonLat: LonLat;\n /** Metres above the ground (default 1.7) */\n height?: number;\n /** Degrees clockwise from north it looks to */\n bearing: number;\n /** Degrees from straight down: 90 level (the default), 180 straight up */\n pitch?: number;\n /** Vertical field of view, degrees (default 75) */\n fov?: number;\n}\n\n/** Layers shown on one side of a vertical line only (`GeoMap.setSwipe`) */\nexport interface SwipeOptions {\n /** CSS pixels from the left of the map */\n position: number;\n layers: readonly Layer[];\n /** The side they show on (default 'left') */\n side?: 'left' | 'right';\n /** Layers shown on the other side only: two meshes of the same place, each on its side, never drawn over each other */\n other?: readonly Layer[];\n}\n\n/** Animation of a camera move */\nexport interface AnimationOptions {\n /** Milliseconds */\n duration?: number;\n /** Progress over time, both 0 to 1 */\n easing?: (t: number) => number;\n}\n\nexport interface FlyToOptions extends AnimationOptions {\n /** How far the flight zooms out on its way, as MapLibre's `curve` (default 1.42) */\n curve?: number;\n /** Average speed in screens per second when `duration` is not given (default 1.2) */\n speed?: number;\n}\n\n/**\n * Tile grid of a raster's URL. 'mercator': Web Mercator (XYZ, WMTS PM), the engine's own. 'equirectangular':\n * longitudes and latitudes (Plate Carrée, EPSG:4326-like), two 256 px tiles side by side at level 0, rows from the\n * north (NASA's Trek WMTS, WorldCRS84Quad). A `TileGrid`: the tile matrices of a WMTS in any CRS (Lambert-93…), or a\n * WMS asked for each tile's box in its CRS. The last two are reprojected into Web Mercator tiles by the map's workers\n * (in the page with `workers: false`).\n */\nexport type RasterGrid = 'mercator' | 'equirectangular' | TileGrid;\n\n/** What `RasterLayer.setStyle` changes */\nexport interface RasterStyle {\n opacity: number;\n /** 0 = greyscale, 1 = original colors */\n saturation: number;\n}\n\n/** Where a new layer goes: under `before`, or on top of the others (under the labels kept on top) */\nexport interface Placement {\n before?: Layer;\n}\n\nexport interface RasterOptions extends Placement {\n /** Tile URL with {z}, {x} and {y} (256 px tiles); unused with a `loader` */\n url: string;\n /** Tile grid of `url` (default 'mercator'); with 'equirectangular', `minZoom` and `maxZoom` are levels of that\n * grid; with a `TileGrid`, they are map zooms, by default those its matrices span */\n grid?: RasterGrid;\n minZoom?: number;\n maxZoom?: number;\n opacity?: number;\n /** 0 = greyscale, 1 = original colors */\n saturation?: number;\n /** Side of the tiles' textures, pixels (default 256): more for sharper tiles drawn by a `loader` */\n size?: number;\n /** Draws each tile instead of fetching `url`: an image of `size` × `size`, null for nothing there; a rejection is\n * retried like a network error */\n loader?: (z: number, x: number, y: number, signal: AbortSignal) => Promise<ImageBitmap | null>;\n /** Credits of the tiles, HTML: shown by the attribution control while the layer is on the map */\n attribution?: string;\n}\n\nexport interface NetworkStyle {\n /** Line width, CSS pixels, or zoom stops `[[zoom, width], …]` (default 2) */\n width: Size;\n /** Values above are drawn as unreached (default 1800) */\n max: number;\n /** Darker line every `contour` value units, 0 for none (default 0) */\n contour: number;\n opacity: number;\n /** Width of the halo drawn under the lines, CSS pixels or zoom stops, 0 for none (default 0): wide and faint, the\n * reached streets add up into a heat map that fills the blocks */\n halo: Size;\n /** Opacity of the halo at the middle of a line, fading quadratically to its sides (default 0.11) */\n haloOpacity: number;\n /** Colors from 0 to `max`: `[[fraction of max, color], …]` (default green to red) */\n ramp: Ramp | undefined;\n /** Color of the parts beyond `max` or unreached (default `rgba(140, 140, 140, 0.25)`) */\n unreachedColor: string;\n /** Share of `max` over which the colors fade out before it, 0 to 1 (default 0) */\n fade: number;\n}\n\nexport interface NetworkOptions extends Partial<NetworkStyle>, Placement {\n /** Node coordinates in degrees: lon0, lat0, lon1, lat1… */\n nodes: Float64Array;\n /** Edges as node index pairs: a0, b0, a1, b1… */\n edges: Uint32Array;\n /** Line of each edge, from A to B: the points of edge e are `points[start[e] .. start[e + 1]]` (lon, lat pairs,\n * counted in points); with fewer than two points an edge is straight. Default: all straight. */\n lines?: { start: Uint32Array; points: Float64Array };\n /** Per edge, the cost of travelling it from A to B then from B to A, in value units (Infinity: closed that way;\n * closed both ways: not drawn). A point along an edge then takes the quickest way there, min(value(A) + cost from\n * A, value(B) + cost from B), as a travel time does. Without costs, values are interpolated along the edges. */\n costs?: Float32Array;\n /** Width factor of each edge (default 1): rail lines wider than streets */\n edgeWidths?: Float32Array;\n}\n\nexport interface Tiles3dStyle {\n /** Screen-space error (CSS pixels) above which a tile is refined: 16 by default, lower is finer and heavier */\n maxScreenSpaceError: number;\n opacity: number;\n /** Size of the points of point cloud tiles (`.pnts`, glTF points), CSS pixels: 2 by default */\n pointSize?: number;\n /** A CSS color multiplying the textures of the meshes, the color of the untextured ones (buildings without\n * textures are light grey without it); none by default */\n color?: string;\n}\n\nexport interface Tiles3dOptions extends Partial<Tiles3dStyle>, Placement {\n /** URL of a `tileset.json` (3D Tiles 1.0 b3dm and pnts, 1.1 glb meshes and points, external tilesets) */\n url: string;\n /** Its heights are altitudes above the geoid (NGF-IGN69), as the IGN's Bâtiments 3D, rather than above the\n * ellipsoid (3D Tiles as specified): each tile raised by the RAF20 geoid, onto the IGN relief (default false) */\n geoid?: boolean;\n}\n\nexport interface MapPointerEvent {\n point: Point;\n /** Undefined above the horizon */\n lonLat: LonLat | undefined;\n}\n\n/** What 'hoverfeature' found under the pointer */\nexport interface MapHoverFeatureEvent extends MapPointerEvent {\n /** The feature under the pointer (see `GeoMap.pickFeature`), undefined if none */\n hit: FeatureHit | undefined;\n}\n\n/** What a pick looks at: within `radius` CSS pixels of the point (default 0), among `layers` (default every layer;\n * the others hide nothing) */\nexport interface PickOptions {\n radius?: number;\n layers?: readonly Layer[];\n}\n\n/** A picked feature: its layer handle, its index there and, for line, circle, fill, extrusion, point cloud and 3D\n * Tiles layers, the feature itself (a building of 3D Tiles with its properties) */\nexport interface FeatureHit {\n layer: Layer;\n index: number;\n feature: Feature | undefined;\n}\n\nexport interface MapEvents {\n /** The camera started moving (a gesture, an animation or `setCamera`) */\n movestart: Camera;\n /** The camera moved */\n move: Camera;\n /** The camera stopped: no gesture held, no animation running */\n moveend: Camera;\n /** The map changed size (CSS pixels) */\n resize: { width: number; height: number };\n /** The pointer moved over the map (at most once per frame, not while dragging) */\n hover: MapPointerEvent;\n /** What is under the pointer, picked without stalling the GPU: a frame or two after 'hover', only while listened to\n * (radius and layers in `GeoMap.hoverPicking`) */\n hoverfeature: MapHoverFeatureEvent;\n /** Click without drag */\n click: MapPointerEvent;\n /** A frame was drawn; duration of the engine call in milliseconds */\n render: { ms: number };\n /** Everything in view is loaded and drawn, nothing moves: the end of a load, once after each change (as MapLibre's\n * `idle`). Tiles requested by the first frame count, so it never fires before they arrive. */\n idle: Record<string, never>;\n /** The pointer left the canvas (a mouse going out of the map, or onto a control or marker) */\n leave: Record<string, never>;\n}\n\n/** What a layer handle needs from its map */\nexport interface LayerHost {\n readonly engine: Engine;\n requestRender(): void;\n /** Forgets a removed layer */\n detach(layer: Layer): void;\n /** Moves a layer under `before`, or on top */\n moveLayer(layer: Layer, before: Layer | undefined): void;\n /** A layer created again in the engine (new id): put at the place of its old id, which is removed */\n replaceLayer(layer: Layer, old: number): void;\n /** Resolves once the map is idle (everything in view loaded and drawn) */\n whenIdle(): Promise<void>;\n /** Work the map waits on before it is idle (`GeoMap.track`) */\n track<T>(work: Promise<T>): Promise<T>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,0CAA0C","sourcesContent":["/** Public types of the `isard` package */\n\nimport type { TileGrid } from './basemap/grid.ts';\nimport type { DecoderUrls } from './decoding/decoders.ts';\nimport type { Feature, Ramp, Size } from './layers/features.ts';\nimport type { Layer } from './layers/layers.ts';\nimport type { AttributionOptions } from './ui/controls.ts';\nimport type { Camera, Engine } from './wasm/isard.js';\n\nexport type LonLat = [lon: number, lat: number];\nexport type Point = [x: number, y: number];\n\n/**\n * The named basemaps. OpenFreeMap's vector styles, OpenStreetMap data worldwide, their labels above the other layers:\n * `osm-positron` (light grey, quiet: data over it reads first), `osm-liberty` and `osm-bright` (in colour), `osm-dark`\n * (near black: bright data over it, a wind's particles, lights). The\n * Géoplateforme's (IGN, France): rasters (`ign-plan`, `ign-plan-grey`, `ign-ortho`, the aerial photographs) or vector\n * tiles with their labels (`ign-plan-vector`, `ign-plan-grey-vector`, the PLAN.IGN styles).\n */\nexport type BasemapName =\n | 'osm-positron'\n | 'osm-liberty'\n | 'osm-bright'\n | 'osm-dark'\n | 'ign-plan'\n | 'ign-plan-grey'\n | 'ign-ortho'\n | 'ign-plan-vector'\n | 'ign-plan-grey-vector'\n | 'none';\n\n/** A basemap by name (see `BasemapName`) */\nexport type Basemap = BasemapName;\n\n/**\n * The Earth's named terrain models. `'terrain-tiles'`: worldwide, the Terrain Tiles of AWS's open data registry\n * (SRTM, EU-DEM, GMTED… merged by Mapzen, 30 m in most places), the sea floor flattened at sea level. `'ign'`: France,\n * the IGN's RGE ALTI from the Géoplateforme (1 to 5 m), raised by the RAF20 geoid to heights above the ellipsoid.\n */\nexport type TerrainModel = 'terrain-tiles' | 'ign';\n\n/** How tiles encode their altitudes: `'float32'`, raw little-endian floats (`image/x-bil;bits=32`, an ArcGIS raw\n * grid); `'terrarium'`, the colors of a PNG, `R × 256 + G + B / 256 - 32768`; `'mapbox'`, those of Terrain-RGB,\n * `(R × 65536 + G × 256 + B) / 10 - 10000` */\nexport type TerrainEncoding = 'float32' | 'terrarium' | 'mapbox';\n\n/**\n * How tiles load and show. 'immediate' (default): everything visible loads, tiles show as soon as they arrive.\n * 'smooth': during flights the levels flown through are skipped, off-center tiles wait while the camera moves, tiles\n * fade in; fewer downloads, for slow networks or GPUs.\n */\nexport type LoadingMode = 'immediate' | 'smooth';\n\n/** 'globe': a sphere at low zoom, blending into Web Mercator between zooms 5 and 7, up to three levels later under a\n * tilted camera (it sees much farther than its center: the horizon stays curved) */\nexport type Projection = 'globe' | 'mercator';\n\n/** A body to draw the map on, other than the named ones (`CelestialBody`) */\nexport interface BodyOptions {\n /** Equatorial radius, metres */\n radius: number;\n /** Flattening of its ellipsoid, 0 for a sphere (default 0) */\n flattening?: number;\n /** An atmosphere: its halo around the globe, true for the Earth's light blue, or a CSS color (its alpha the\n * halo's strength) (default false) */\n atmosphere?: boolean | string;\n /** Color of the globe where no tile covers it (past the Web Mercator latitudes, 85°), a CSS color (default\n * `#808080`) */\n color?: string;\n /** Lowest and highest altitudes of its ground, metres around the ellipsoid: what its relief may raise into view\n * (default ±1 % of the radius) */\n relief?: [lowest: number, highest: number];\n}\n\n/**\n * The body the map is drawn on: 'earth' (WGS 84, the default), 'moon' (a sphere of 1 737 400 m, no atmosphere),\n * 'mars' (a sphere of 3 396 190 m, its equatorial radius, a thin dusty halo; planetocentric latitudes) or another\n * one. Zoom levels keep their meaning on screen (the Web Mercator tile pyramid), their metres follow the body:\n * altitudes, relief, buildings, 3D Tiles. Off the Earth, the map has none of the Earth's defaults: no basemap, no\n * credits, and space for its background; the Moon and Mars have NASA's relief for `terrain: true`.\n */\nexport type CelestialBody = 'earth' | 'moon' | 'mars' | BodyOptions;\n\nexport interface GeoMapOptions extends Partial<Camera> {\n /** The body the map is drawn on (default 'earth'); set at creation */\n body?: CelestialBody;\n /** Default 'globe' */\n projection?: Projection;\n /** Default 'immediate' */\n loading?: LoadingMode;\n /** The basemap (default 'osm-positron'; 'none' off the Earth) */\n basemap?: Basemap;\n /** Opacity of the IGN hillshade over the basemap (France, Géoplateforme), 0 for none (default 0) */\n hillshade?: number;\n /** Color behind the map (sky of tilted flat views), a CSS color (default `#f2f2f0`; black off the Earth) */\n background?: string;\n /** Space behind the globe: stars and atmosphere halo, fading out as the globe turns flat (default true) */\n sky?: boolean;\n /** The sun casting the shadows of buildings, trees, models and the relief (`setSun`); none by default */\n sun?: SunOptions;\n /** Relief under the basemap: true for the body's terrain model (on the Earth the worldwide Terrain Tiles; NASA's on\n * the Moon and Mars: LOLA, MOLA), one of the Earth's models by name (`'ign'`: France, RGE ALTI), or its options\n * (default false; on another body, its `url` is required). Network layers are draped on it */\n terrain?: boolean | TerrainModel | TerrainOptions;\n minZoom?: number;\n maxZoom?: number;\n /** Highest pitch, degrees, up to 85 (default 70) */\n maxPitch?: number;\n /** Sky over the plane, seen when the camera is tilted towards the horizon, and the fog the ground fades into\n * (MapLibre's `setSky`); default none: the background color */\n atmosphere?: AtmosphereOptions;\n /** Mouse, touch and keyboard controls (default true) */\n interactive?: boolean;\n /** Keyboard controls once the map has the focus (it is reached with Tab): arrows pan, Shift + arrows rotate and\n * tilt, + and - zoom (Shift: two levels), 0 faces north and levels the view (default true; none when not\n * `interactive`) */\n keyboard?: boolean;\n /** Accessible name of the map, read by screen readers (default 'Map') */\n ariaLabel?: string;\n /** A preset of map options (`IGN_PRESETS`: `'ign'`, `'ign-3d'`, `'ign-ortho-3d'`), the other options over it */\n preset?: 'ign' | 'ign-3d' | 'ign-ortho-3d';\n /** The folder isard's files are served from (its engines, `isard_bg.wasm`, `isard_core_bg.wasm`,\n * `isard_points_bg.wasm`, `isard_tess_bg.wasm`, `isard_grid_bg.wasm`, and its workers, `decoder.worker.js`, `basemap.worker.js`): one option for a bundler that\n * moves them, the `…Url` options below for each one. `isard/vite` sets it for the whole page; default next to the\n * module */\n assetsUrl?: string | URL;\n /** Where to load the engine with 3D Tiles from (`isard_bg.wasm`), when a bundler does not resolve the default URL.\n * Given without `coreWasmUrl`, maps load this engine from the start */\n wasmUrl?: string | URL;\n /** Where to load the engine without 3D Tiles from (`isard_core_bg.wasm`, a third smaller), when a bundler does not\n * resolve the default URL. Maps load it first, and the engine with 3D Tiles (`wasmUrl`) for their first 3D Tiles\n * layer only */\n coreWasmUrl?: string | URL;\n /** Where the decoding workers load the point cloud module from (`isard_points_bg.wasm`, the LAZ decoder of COPC),\n * when a bundler does not resolve the default URL. Loaded with the first point cloud only */\n pointsWasmUrl?: string | URL;\n /** Where the basemap workers load the tessellation module from (`isard_tess_bg.wasm`: the vector tiles drawn as\n * geometry, `vectorTiles().vectors()`, made ready for the GPU off the main thread), when a bundler does not resolve\n * the default URL. Loaded with the first tile of geometry; without it, the main thread does that work */\n tessWasmUrl?: string | URL;\n /** Where the workers load the grid module from (`isard_grid_bg.wasm`: GRIB2 and NetCDF files read by\n * `map.readGrids`), when a bundler does not resolve the default URL. Loaded with the first file */\n gridWasmUrl?: string | URL;\n /** Load the engine with 3D Tiles from the start (default false: it is loaded when the first 3D Tiles layer or glTF\n * model is added, the map then moving its camera and layers onto it, a stall of about a frame or two). For a map that shows 3D Tiles\n * at once: one engine downloaded instead of two. `'preload'`: the map starts on the engine without 3D Tiles and\n * downloads and compiles the other once idle, without running it: its first 3D Tiles layer does not wait for the\n * download (for a map that will show 3D Tiles later, on demand) */\n tiles3d?: boolean | 'preload';\n /** Where to load the vector basemap worker from, when a bundler does not resolve the default URL */\n basemapWorkerUrl?: string | URL;\n /** Texture size of the vector basemap's tiles, pixels (default 512: lines and edges sharp at every zoom on a screen\n * of pixel ratio 1). 256: a quarter of the drawing in the workers, of the uploads and of the GPU memory, for lines\n * and edges a little softer between two zoom levels (the tiles are shown 181 to 362 CSS pixels wide) */\n basemapTileSize?: number;\n /** Glyphs of the symbol layers: a URL with `{fontstack}` and `{range}` (MapLibre's glyph format; default\n * OpenFreeMap's fonts, Noto Sans). A vector basemap's labels take the glyphs of its style */\n glyphs?: string;\n /** Workers decoding 3D Tiles off the main thread: a count, or false to decode on the main thread (default: cores - 1,\n * 1 to 4). False (or 0) also decodes the PNG relief and reprojects the equirectangular rasters on the main thread,\n * else done by the vector basemap's workers */\n workers?: number | false;\n /** Where to load the decoding worker from, when a bundler does not resolve the default URL */\n workerUrl?: string | URL;\n /** Folders of the Draco and Basis Universal decoders, loaded by the workers on first use (default: the official\n * builds on gstatic.com and jsDelivr; self-host them for offline or locked-down networks). They run through\n * `new Function`: a Content Security Policy needs `'unsafe-eval'` (see `DecoderUrls`) */\n decoders?: Partial<DecoderUrls>;\n /** Credits at the bottom right: false for none, or its options (default true: the credits of the basemap,\n * hillshade and relief in use, compact on maps narrower than 640 px) */\n attributionControl?: boolean | AttributionOptions;\n}\n\nexport interface TerrainOptions {\n /** One of the Earth's named models (default `'terrain-tiles'` on the Earth); unused with a `url` */\n model?: TerrainModel;\n /** Altitudes of 256 × 256 tiles in `encoding`: a WMS GetMap URL with {bbox} (EPSG:3857 on the Earth, the body's\n * Mercator metres elsewhere: the sphere of its radius), a tile URL with {z}, {x} and {y}, or an ArcGIS image service\n * (a URL ending in `/ImageServer`), asked for raw altitudes in the body's Mercator (default: the `model`'s; on the\n * Moon and Mars, NASA's Trek LOLA and MOLA models) */\n url?: string;\n /** How the tiles of `url` encode their altitudes (default `'float32'`); `'terrarium'` and `'mapbox'` take a URL with\n * {z}, {x} and {y} */\n encoding?: TerrainEncoding;\n /** Vertical exaggeration, 1 for the true relief (default 1) */\n exaggeration?: number;\n /** Finest level of the relief, up to 15 (default 15; 14 for the Terrain Tiles, 8 for the Moon's and Mars's models). It\n * starts at level 6 on the Earth, coarser on bodies of a larger relief for their size (3 on the Moon and Mars) */\n maxZoom?: number;\n /** Altitudes over mainland France raised by the height of the RAF20 geoid (the French one, 0 away from France), to\n * heights above the ellipsoid (those of 3D Tiles); false keeps the altitudes as served (NGF-IGN69 for the IGN's)\n * (default true for the `'ign'` model, false otherwise) */\n geoid?: boolean;\n}\n\n/** Sky, horizon and fog over the plane, with the names and meanings of MapLibre's `setSky` */\nexport interface AtmosphereOptions {\n /** A CSS color (default `#9cc7ec`) */\n skyColor?: string;\n /** (default `#e8f1f8`) */\n horizonColor?: string;\n /** (default `#f2f5f8`) */\n fogColor?: string;\n /** Blend from the horizon to the sky color, share of the field of view above the horizon, 0-1 (default 0.6) */\n skyHorizonBlend?: number;\n /** Blend from the horizon to the fog color below the horizon, 0-1 (default 0.7) */\n horizonFogBlend?: number;\n /** Share of the distance to the far plane over which the ground fades into the fog, 0-1 (default 0.4) */\n fogGroundBlend?: number;\n}\n\n/** The sun casting shadows (`GeoMap.setSun`): where it stands, by date or by hand, and how dark its shadows are */\nexport interface SunOptions {\n /** The time: the sun where it stands then over the map's center (default now, unless `azimuth` and `altitude`) */\n date?: Date;\n /** Degrees clockwise from north, with `altitude`: the sun placed by hand */\n azimuth?: number;\n /** Degrees above the horizon; at or under it, no shadows */\n altitude?: number;\n /** How dark the shadows are, 0 to 1 (default 0.35) */\n opacity?: number;\n /** How dark the night is, 0 to 1: the scene tinted in its blue, the windows of the buildings and the streets of\n * `vectors()` lit, the labels light on dark. By default from the sun's altitude: falling from 6° above the horizon\n * to 6° under it */\n night?: number;\n}\n\n/** What can be seen from a point (`GeoMap.setViewshed`); with several observers, the colors, the opacity and the\n * cone's color are the first one's */\nexport interface ViewshedOptions {\n /** The observer */\n position: LonLat;\n /** Metres above the ground (default 1.7, eye level) */\n height?: number;\n /** Metres around the observer that are tinted (default 1000) */\n range?: number;\n /** A CSS color for what is seen (default `#2f9e44`) */\n visibleColor?: string;\n /** A CSS color for what is hidden (default `#e03131`) */\n hiddenColor?: string;\n /** How strongly the colors tint the scene, multiplied into it so that its textures and shading stay, 0-1 (default\n * 0.7) */\n opacity?: number;\n /** A CSS color for the cone drawn in 3D (one way only): its fan through the axis, at the eye's height and tilted\n * with it, from the eye to the range; solid where nothing hides it, faint behind the scene; none by default */\n coneColor?: string;\n /** To look one way only (a camera, a lookout), degrees clockwise from north; all around without it */\n direction?: number;\n /** Degrees above the horizon the cone looks, negative below (default 0) */\n tilt?: number;\n /** Angle of view across, degrees (default 60) */\n fov?: number;\n /** Angle of view up and down, degrees (default 40) */\n verticalFov?: number;\n}\n\n/** An eye at street level (`GeoMap.setFirstPerson`) */\nexport interface FirstPersonView {\n /** Where it stands */\n lonLat: LonLat;\n /** Metres above the ground (default 1.7) */\n height?: number;\n /** Degrees clockwise from north it looks to */\n bearing: number;\n /** Degrees from straight down: 90 level (the default), 180 straight up */\n pitch?: number;\n /** Vertical field of view, degrees (default 75) */\n fov?: number;\n}\n\n/** Layers shown on one side of a vertical line only (`GeoMap.setSwipe`) */\nexport interface SwipeOptions {\n /** CSS pixels from the left of the map */\n position: number;\n layers: readonly Layer[];\n /** The side they show on (default 'left') */\n side?: 'left' | 'right';\n /** Layers shown on the other side only: two meshes of the same place, each on its side, never drawn over each other */\n other?: readonly Layer[];\n}\n\n/** Animation of a camera move */\nexport interface AnimationOptions {\n /** Milliseconds */\n duration?: number;\n /** Progress over time, both 0 to 1 */\n easing?: (t: number) => number;\n}\n\nexport interface FlyToOptions extends AnimationOptions {\n /** How far the flight zooms out on its way, as MapLibre's `curve` (default 1.42) */\n curve?: number;\n /** Average speed in screens per second when `duration` is not given (default 1.2) */\n speed?: number;\n}\n\n/**\n * Tile grid of a raster's URL. 'mercator': Web Mercator (XYZ, WMTS PM), the engine's own. 'equirectangular':\n * longitudes and latitudes (Plate Carrée, EPSG:4326-like), two 256 px tiles side by side at level 0, rows from the\n * north (NASA's Trek WMTS, WorldCRS84Quad). A `TileGrid`: the tile matrices of a WMTS in any CRS (Lambert-93…), or a\n * WMS asked for each tile's box in its CRS. The last two are reprojected into Web Mercator tiles by the map's workers\n * (in the page with `workers: false`).\n */\nexport type RasterGrid = 'mercator' | 'equirectangular' | TileGrid;\n\n/** What `RasterLayer.setStyle` changes */\nexport interface RasterStyle {\n opacity: number;\n /** 0 = greyscale, 1 = original colors */\n saturation: number;\n}\n\n/** Where a new layer goes: under `before`, or on top of the others (under the labels kept on top) */\nexport interface Placement {\n before?: Layer;\n}\n\nexport interface RasterOptions extends Placement {\n /** Tile URL with {z}, {x} and {y} (256 px tiles); unused with a `loader` */\n url: string;\n /** Tile grid of `url` (default 'mercator'); with 'equirectangular', `minZoom` and `maxZoom` are levels of that\n * grid; with a `TileGrid`, they are map zooms, by default those its matrices span */\n grid?: RasterGrid;\n minZoom?: number;\n maxZoom?: number;\n opacity?: number;\n /** 0 = greyscale, 1 = original colors */\n saturation?: number;\n /** Side of the tiles' textures, pixels (default 256): more for sharper tiles drawn by a `loader` */\n size?: number;\n /** Draws each tile instead of fetching `url`: an image of `size` × `size`, null for nothing there; a rejection is\n * retried like a network error */\n loader?: (z: number, x: number, y: number, signal: AbortSignal) => Promise<ImageBitmap | null>;\n /** Credits of the tiles, HTML: shown by the attribution control while the layer is on the map */\n attribution?: string;\n}\n\nexport interface NetworkStyle {\n /** Line width, CSS pixels, or zoom stops `[[zoom, width], …]` (default 2) */\n width: Size;\n /** Values above are drawn as unreached (default 1800) */\n max: number;\n /** Darker line every `contour` value units, 0 for none (default 0) */\n contour: number;\n opacity: number;\n /** Width of the halo drawn under the lines, CSS pixels or zoom stops, 0 for none (default 0): wide and faint, the\n * reached streets add up into a heat map that fills the blocks */\n halo: Size;\n /** Opacity of the halo at the middle of a line, fading quadratically to its sides (default 0.11) */\n haloOpacity: number;\n /** Colors from 0 to `max`: `[[fraction of max, color], …]` (default green to red) */\n ramp: Ramp | undefined;\n /** Color of the parts beyond `max` or unreached (default `rgba(140, 140, 140, 0.25)`) */\n unreachedColor: string;\n /** Share of `max` over which the colors fade out before it, 0 to 1 (default 0) */\n fade: number;\n}\n\nexport interface NetworkOptions extends Partial<NetworkStyle>, Placement {\n /** Node coordinates in degrees: lon0, lat0, lon1, lat1… */\n nodes: Float64Array;\n /** Edges as node index pairs: a0, b0, a1, b1… */\n edges: Uint32Array;\n /** Line of each edge, from A to B: the points of edge e are `points[start[e] .. start[e + 1]]` (lon, lat pairs,\n * counted in points); with fewer than two points an edge is straight. Default: all straight. */\n lines?: { start: Uint32Array; points: Float64Array };\n /** Per edge, the cost of travelling it from A to B then from B to A, in value units (Infinity: closed that way;\n * closed both ways: not drawn). A point along an edge then takes the quickest way there, min(value(A) + cost from\n * A, value(B) + cost from B), as a travel time does. Without costs, values are interpolated along the edges. */\n costs?: Float32Array;\n /** Width factor of each edge (default 1): rail lines wider than streets */\n edgeWidths?: Float32Array;\n}\n\nexport interface Tiles3dStyle {\n /** Screen-space error (CSS pixels) above which a tile is refined: 16 by default, lower is finer and heavier */\n maxScreenSpaceError: number;\n opacity: number;\n /** Size of the points of point cloud tiles (`.pnts`, glTF points), CSS pixels: 2 by default */\n pointSize?: number;\n /** A CSS color multiplying the textures of the meshes, the color of the untextured ones (buildings without\n * textures are light grey without it); none by default */\n color?: string;\n}\n\nexport interface Tiles3dOptions extends Partial<Tiles3dStyle>, Placement {\n /** URL of a `tileset.json` (3D Tiles 1.0 b3dm and pnts, 1.1 glb meshes and points, external tilesets) */\n url: string;\n /** Its heights are altitudes above the geoid (NGF-IGN69), as the IGN's Bâtiments 3D, rather than above the\n * ellipsoid (3D Tiles as specified): each tile raised by the RAF20 geoid, onto the IGN relief (default false) */\n geoid?: boolean;\n /** The walls of its untextured meshes show windows: glass by day, some lit at night (`setFacades`; default false) */\n facades?: boolean;\n}\n\nexport interface MapPointerEvent {\n point: Point;\n /** Undefined above the horizon */\n lonLat: LonLat | undefined;\n}\n\n/** What 'hoverfeature' found under the pointer */\nexport interface MapHoverFeatureEvent extends MapPointerEvent {\n /** The feature under the pointer (see `GeoMap.pickFeature`), undefined if none */\n hit: FeatureHit | undefined;\n}\n\n/** What a pick looks at: within `radius` CSS pixels of the point (default 0), among `layers` (default every layer;\n * the others hide nothing) */\nexport interface PickOptions {\n radius?: number;\n layers?: readonly Layer[];\n}\n\n/** A picked feature: its layer handle, its index there and, for line, circle, fill, extrusion, point cloud and 3D\n * Tiles layers, the feature itself (a building of 3D Tiles with its properties) */\nexport interface FeatureHit {\n layer: Layer;\n index: number;\n feature: Feature | undefined;\n}\n\nexport interface MapEvents {\n /** The camera started moving (a gesture, an animation or `setCamera`) */\n movestart: Camera;\n /** The camera moved */\n move: Camera;\n /** The camera stopped: no gesture held, no animation running */\n moveend: Camera;\n /** The map changed size (CSS pixels) */\n resize: { width: number; height: number };\n /** The pointer moved over the map (at most once per frame, not while dragging) */\n hover: MapPointerEvent;\n /** What is under the pointer, picked without stalling the GPU: a frame or two after 'hover', only while listened to\n * (radius and layers in `GeoMap.hoverPicking`) */\n hoverfeature: MapHoverFeatureEvent;\n /** Click without drag */\n click: MapPointerEvent;\n /** A frame was drawn; duration of the engine call in milliseconds */\n render: { ms: number };\n /** Everything in view is loaded and drawn, nothing moves: the end of a load, once after each change (as MapLibre's\n * `idle`). Tiles requested by the first frame count, so it never fires before they arrive. */\n idle: Record<string, never>;\n /** The pointer left the canvas (a mouse going out of the map, or onto a control or marker) */\n leave: Record<string, never>;\n}\n\n/** What a layer handle needs from its map */\nexport interface LayerHost {\n readonly engine: Engine;\n requestRender(): void;\n /** Forgets a removed layer */\n detach(layer: Layer): void;\n /** Moves a layer under `before`, or on top */\n moveLayer(layer: Layer, before: Layer | undefined): void;\n /** A layer created again in the engine (new id): put at the place of its old id, which is removed */\n replaceLayer(layer: Layer, old: number): void;\n /** Resolves once the map is idle (everything in view loaded and drawn) */\n whenIdle(): Promise<void>;\n /** Work the map waits on before it is idle (`GeoMap.track`) */\n track<T>(work: Promise<T>): Promise<T>;\n}\n"]}
|
package/dist/ui/interaction.d.ts
CHANGED
|
@@ -28,6 +28,8 @@ export declare class Interaction {
|
|
|
28
28
|
private readonly pointers;
|
|
29
29
|
private readonly cleanup;
|
|
30
30
|
private wheel;
|
|
31
|
+
/** What the two fingers on the map do, once told (`twoFingerGesture`) */
|
|
32
|
+
private gesture;
|
|
31
33
|
/** Recent pan moves, for the release speed: [time, dx, dy] */
|
|
32
34
|
private trail;
|
|
33
35
|
private moved;
|
|
@@ -36,6 +38,8 @@ export declare class Interaction {
|
|
|
36
38
|
private rect;
|
|
37
39
|
/** A double click zooms in (Shift: out); off while the page takes double clicks (ending a drawing) */
|
|
38
40
|
doubleClickZoom: boolean;
|
|
41
|
+
/** A drag that turns and tilts goes around what is under the pointer where it starts (else around the center) */
|
|
42
|
+
rotateAroundPointer: boolean;
|
|
39
43
|
constructor(map: GeoMap, options?: {
|
|
40
44
|
keyboard?: boolean;
|
|
41
45
|
});
|
package/dist/ui/interaction.js
CHANGED
|
@@ -10,6 +10,10 @@ const WHEEL_RATE = 1 / 300;
|
|
|
10
10
|
const WHEEL_EASE = 0.3;
|
|
11
11
|
/** Degrees per pixel when rotating or tilting with the mouse */
|
|
12
12
|
const ROTATE_RATE = 0.4;
|
|
13
|
+
/** Degrees of tilt per CSS pixel two fingers move up or down together (MapLibre's rate) */
|
|
14
|
+
const TOUCH_PITCH_RATE = 0.5;
|
|
15
|
+
/** CSS pixels a finger moves before a two-finger gesture is told: a tilt or a pinch */
|
|
16
|
+
const GESTURE_THRESHOLD = 6;
|
|
13
17
|
/** A press that moves less than this (CSS pixels) is a click */
|
|
14
18
|
const CLICK_TOLERANCE = 4;
|
|
15
19
|
/** Pan speed kept on release, decaying with this time constant (ms) */
|
|
@@ -75,11 +79,31 @@ const editable = (target) => {
|
|
|
75
79
|
return false;
|
|
76
80
|
return target.isContentEditable || ['INPUT', 'TEXTAREA', 'SELECT'].includes(target.tagName);
|
|
77
81
|
};
|
|
82
|
+
/**
|
|
83
|
+
* What two fingers do, once both moved (or one far, alone): a tilt if they lie side by side and both move up or down
|
|
84
|
+
* together (as MapLibre and Google Earth take it), else a pinch (zoom, turn, pan); undefined before. A touch screen
|
|
85
|
+
* sends the fingers' moves one after the other: the first one alone tells nothing yet
|
|
86
|
+
*/
|
|
87
|
+
const twoFingerGesture = (a, b) => {
|
|
88
|
+
const [ma, mb] = [Math.hypot(...a.moved), Math.hypot(...b.moved)];
|
|
89
|
+
const [most, least] = [Math.max(ma, mb), Math.min(ma, mb)];
|
|
90
|
+
if (most < GESTURE_THRESHOLD)
|
|
91
|
+
return undefined;
|
|
92
|
+
if (least < GESTURE_THRESHOLD / 2 && most < 2 * GESTURE_THRESHOLD)
|
|
93
|
+
return undefined;
|
|
94
|
+
const sideBySide = Math.abs(a.point[1] - b.point[1]) < Math.abs(a.point[0] - b.point[0]);
|
|
95
|
+
const vertical = (q) => Math.abs(q.moved[1]) > 2 * Math.abs(q.moved[0]);
|
|
96
|
+
const together = Math.sign(a.moved[1]) === Math.sign(b.moved[1]);
|
|
97
|
+
const both = Math.min(Math.abs(a.moved[1]), Math.abs(b.moved[1])) >= GESTURE_THRESHOLD / 2;
|
|
98
|
+
return sideBySide && vertical(a) && vertical(b) && together && both ? 'tilt' : 'pinch';
|
|
99
|
+
};
|
|
78
100
|
export class Interaction {
|
|
79
101
|
map;
|
|
80
102
|
pointers = new Map();
|
|
81
103
|
cleanup = [];
|
|
82
104
|
wheel = { pending: 0, at: [0, 0] };
|
|
105
|
+
/** What the two fingers on the map do, once told (`twoFingerGesture`) */
|
|
106
|
+
gesture;
|
|
83
107
|
/** Recent pan moves, for the release speed: [time, dx, dy] */
|
|
84
108
|
trail = [];
|
|
85
109
|
moved = false;
|
|
@@ -88,6 +112,8 @@ export class Interaction {
|
|
|
88
112
|
rect;
|
|
89
113
|
/** A double click zooms in (Shift: out); off while the page takes double clicks (ending a drawing) */
|
|
90
114
|
doubleClickZoom = true;
|
|
115
|
+
/** A drag that turns and tilts goes around what is under the pointer where it starts (else around the center) */
|
|
116
|
+
rotateAroundPointer = true;
|
|
91
117
|
constructor(map, options = {}) {
|
|
92
118
|
this.map = map;
|
|
93
119
|
const canvas = map.canvas;
|
|
@@ -152,7 +178,19 @@ export class Interaction {
|
|
|
152
178
|
this.map.canvas.setPointerCapture(e.pointerId);
|
|
153
179
|
const point = this.local(e);
|
|
154
180
|
const rotate = e.button === 2 || e.ctrlKey || e.shiftKey;
|
|
155
|
-
this.pointers.set(e.pointerId, { point, start: point, button: e.button, rotate });
|
|
181
|
+
this.pointers.set(e.pointerId, { point, start: point, button: e.button, rotate, moved: [0, 0] });
|
|
182
|
+
// A new gesture: told again from here
|
|
183
|
+
this.gesture = undefined;
|
|
184
|
+
this.pointers.forEach((q) => {
|
|
185
|
+
q.moved = [0, 0];
|
|
186
|
+
});
|
|
187
|
+
// A turn goes around what the pointer grabbed (a roof, a mesh, the relief); a pinch around the center
|
|
188
|
+
if (rotate && this.rotateAroundPointer && this.pointers.size === 1 && !this.map.firstPerson) {
|
|
189
|
+
this.map.engine.setPivot(...point);
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
this.map.engine.clearPivot();
|
|
193
|
+
}
|
|
156
194
|
this.trail = [];
|
|
157
195
|
this.moved = false;
|
|
158
196
|
// Grabbing the map stops any running animation (inertia, wheel zoom, easeTo)
|
|
@@ -180,7 +218,14 @@ export class Interaction {
|
|
|
180
218
|
}
|
|
181
219
|
const engine = this.map.engine;
|
|
182
220
|
const other = [...this.pointers.values()].find((q) => q !== p);
|
|
183
|
-
|
|
221
|
+
p.moved = [p.moved[0] + dx, p.moved[1] + dy];
|
|
222
|
+
if (this.pointers.size === 2 && other)
|
|
223
|
+
this.gesture ??= twoFingerGesture(p, other);
|
|
224
|
+
if (this.pointers.size === 2 && this.gesture === 'tilt') {
|
|
225
|
+
// Both fingers up or down: the midpoint moves by half of this one's move
|
|
226
|
+
engine.rotate(0, (-dy / 2) * TOUCH_PITCH_RATE);
|
|
227
|
+
}
|
|
228
|
+
else if (this.pointers.size === 2 && other && this.gesture === 'pinch') {
|
|
184
229
|
// Pinch: zoom by the change of spread, turn by the change of angle, pan by the midpoint
|
|
185
230
|
const before = Math.hypot(p.point[0] - other.point[0], p.point[1] - other.point[1]);
|
|
186
231
|
const after = Math.hypot(point[0] - other.point[0], point[1] - other.point[1]);
|
|
@@ -191,6 +236,9 @@ export class Interaction {
|
|
|
191
236
|
engine.zoomAt(Math.log2(after / before), ...mid(point));
|
|
192
237
|
engine.rotate((-(angle(point) - angle(p.point)) * 180) / Math.PI, 0);
|
|
193
238
|
}
|
|
239
|
+
else if (this.pointers.size === 2) {
|
|
240
|
+
// Two fingers whose gesture is not told yet: a few pixels left out
|
|
241
|
+
}
|
|
194
242
|
else if (p.rotate) {
|
|
195
243
|
engine.rotate(-dx * ROTATE_RATE, -dy * ROTATE_RATE);
|
|
196
244
|
}
|
|
@@ -206,6 +254,9 @@ export class Interaction {
|
|
|
206
254
|
if (!p)
|
|
207
255
|
return;
|
|
208
256
|
this.pointers.delete(e.pointerId);
|
|
257
|
+
this.gesture = undefined;
|
|
258
|
+
if (p.rotate)
|
|
259
|
+
this.map.engine.clearPivot();
|
|
209
260
|
// The next frame sends 'moveend' if the camera stays
|
|
210
261
|
this.map.requestRender();
|
|
211
262
|
if (!this.moved && e.type === 'pointerup' && p.button === 0 && this.pointers.size === 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interaction.js","sourceRoot":"","sources":["../../src/ui/interaction.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Mouse, touch and keyboard controls. Every gesture only updates the camera and asks for a frame: the engine draws at most\n * once per display refresh, whatever the event rate of the device.\n */\n\nimport type { GeoMap } from '../map.ts';\nimport type { Point } from '../types.ts';\nimport { latitude, mercatorX, mercatorY, RAD } from '../util/geo.ts';\nimport { clamp } from '../util/math.ts';\nimport type { Camera } from '../wasm/isard.js';\n\n/** Zoom levels per wheel pixel (a mouse notch is about 100 px: 1/3 of a level) */\nconst WHEEL_RATE = 1 / 300;\n/** Share of the remaining wheel zoom applied per frame (smooth, about 150 ms to settle) */\nconst WHEEL_EASE = 0.3;\n/** Degrees per pixel when rotating or tilting with the mouse */\nconst ROTATE_RATE = 0.4;\n/** A press that moves less than this (CSS pixels) is a click */\nconst CLICK_TOLERANCE = 4;\n/** Pan speed kept on release, decaying with this time constant (ms) */\nconst INERTIA_DECAY = 280;\n\n/** CSS pixels per arrow key press */\nconst KEY_PAN = 100;\n/** Degrees per Shift + left or right arrow */\nconst KEY_BEARING = 15;\n/** Degrees per Shift + up or down arrow */\nconst KEY_PITCH = 10;\n/** Duration of the moves made by keys, milliseconds */\nconst KEY_DURATION = 300;\n\n/** What a key does to the camera: a pan in CSS pixels, a zoom, rotation or tilt step, or facing north */\nexport type KeyAction = { pan: Point } | { zoom: number } | { bearing: number } | { pitch: number } | { reset: true };\n\n/** The action of a key (`KeyboardEvent.key`), as MapLibre's: arrows pan (with Shift: rotate and tilt), + and - zoom\n * (with Shift: two levels), 0 faces north and levels the view */\nexport const keyAction = (key: string, shift: boolean): KeyAction | undefined => {\n switch (key) {\n case 'ArrowLeft':\n return shift ? { bearing: -KEY_BEARING } : { pan: [-KEY_PAN, 0] };\n case 'ArrowRight':\n return shift ? { bearing: KEY_BEARING } : { pan: [KEY_PAN, 0] };\n case 'ArrowUp':\n return shift ? { pitch: KEY_PITCH } : { pan: [0, -KEY_PAN] };\n case 'ArrowDown':\n return shift ? { pitch: -KEY_PITCH } : { pan: [0, KEY_PAN] };\n case '+':\n case '=':\n return { zoom: shift ? 2 : 1 };\n case '-':\n case '_':\n return { zoom: shift ? -2 : -1 };\n case '0':\n return { reset: true };\n default:\n return undefined;\n }\n};\n\n/** The camera after a key's action: a pan moves the center by that many CSS pixels on screen (the ground in view,\n * turned with the bearing, stretched by the tilt) */\nexport const keyCamera = (action: KeyAction, camera: Camera): Partial<Camera> => {\n if ('zoom' in action) return { zoom: camera.zoom + action.zoom };\n if ('bearing' in action) return { bearing: camera.bearing + action.bearing };\n if ('pitch' in action) return { pitch: Math.max(0, camera.pitch + action.pitch) };\n if ('reset' in action) return { bearing: 0, pitch: 0 };\n\n const b = camera.bearing * RAD;\n const [sx, sy] = [action.pan[0], action.pan[1] / Math.max(0.25, Math.cos(camera.pitch * RAD))];\n // Web Mercator units (0 to 1 across the world, y down); the world is 512 CSS pixels at zoom 0\n const world = 512 * 2 ** camera.zoom;\n const dx = (sx * Math.cos(b) - sy * Math.sin(b)) / world;\n const dy = (sx * Math.sin(b) + sy * Math.cos(b)) / world;\n const [lon, lat] = camera.center;\n const x = mercatorX(lon) + dx;\n const y = clamp(mercatorY(lat) + dy, 0, 1);\n const wrapped = ((((x * 360) % 360) + 360) % 360) - 180;\n\n return { center: [wrapped, latitude(y)] };\n};\n\n/** An element that takes the keys typed in it */\nconst editable = (target: EventTarget | null): boolean => {\n if (!(target instanceof HTMLElement)) return false;\n\n return target.isContentEditable || ['INPUT', 'TEXTAREA', 'SELECT'].includes(target.tagName);\n};\n\ninterface Pointer {\n point: Point;\n start: Point;\n button: number;\n rotate: boolean;\n}\n\nexport class Interaction {\n private readonly pointers = new Map<number, Pointer>();\n private readonly cleanup: (() => void)[] = [];\n private wheel: { pending: number; at: Point } = { pending: 0, at: [0, 0] };\n /** Recent pan moves, for the release speed: [time, dx, dy] */\n private trail: [number, number, number][] = [];\n private moved = false;\n /** The canvas's place on the page, read once: reading it on every pointer move would force a layout each time.\n * Read again after a resize, a scroll, and when a pointer comes in or goes down */\n private rect: DOMRect | undefined;\n /** A double click zooms in (Shift: out); off while the page takes double clicks (ending a drawing) */\n doubleClickZoom = true;\n\n constructor(\n private readonly map: GeoMap,\n options: { keyboard?: boolean } = {},\n ) {\n const canvas = map.canvas;\n const listen = <K extends keyof HTMLElementEventMap>(\n type: K,\n handler: (e: HTMLElementEventMap[K]) => void,\n options?: AddEventListenerOptions,\n ) => {\n canvas.addEventListener(type, handler, options);\n this.cleanup.push(() => canvas.removeEventListener(type, handler));\n };\n const moved = () => {\n this.rect = undefined;\n };\n\n listen('pointerenter', moved);\n // Scrolls of the page or of any element holding the map\n if (typeof addEventListener === 'function') {\n addEventListener('scroll', moved, { capture: true, passive: true });\n this.cleanup.push(() => removeEventListener('scroll', moved, { capture: true }));\n }\n this.cleanup.push(map.on('resize', moved));\n listen('pointerdown', (e) => {\n this.rect = undefined;\n this.down(e);\n });\n listen('pointermove', (e) => this.move(e));\n listen('pointerup', (e) => this.up(e));\n listen('pointercancel', (e) => this.up(e));\n listen('pointerleave', (e) => {\n if (e.pointerType !== 'mouse') return;\n map.hover(undefined);\n map.emit('leave', {});\n });\n\n // On the container, the wheel zooms over markers and popups too\n const container = map.getContainer();\n const wheel = (e: WheelEvent) => this.onWheel(e);\n\n container.addEventListener('wheel', wheel, { passive: false });\n this.cleanup.push(() => container.removeEventListener('wheel', wheel));\n listen('dblclick', (e) => {\n if (this.doubleClickZoom && !this.map.firstPerson) this.zoomBy(e.shiftKey ? -1 : 1, this.local(e));\n });\n listen('contextmenu', (e) => e.preventDefault());\n if (options.keyboard ?? true) {\n // On the container: the keys work with the focus on a marker or a control too\n const key = (e: KeyboardEvent) => this.onKey(e);\n\n container.addEventListener('keydown', key);\n this.cleanup.push(() => container.removeEventListener('keydown', key));\n }\n }\n\n destroy(): void {\n this.cleanup.forEach((off) => {\n off();\n });\n }\n\n /** A gesture holds the map (pointers down): the camera has not stopped moving */\n get active(): boolean {\n return this.pointers.size > 0;\n }\n\n private local(e: MouseEvent): Point {\n this.rect ??= this.map.canvas.getBoundingClientRect();\n\n return [e.clientX - this.rect.left, e.clientY - this.rect.top];\n }\n\n private down(e: PointerEvent): void {\n this.map.canvas.setPointerCapture(e.pointerId);\n\n const point = this.local(e);\n const rotate = e.button === 2 || e.ctrlKey || e.shiftKey;\n\n this.pointers.set(e.pointerId, { point, start: point, button: e.button, rotate });\n this.trail = [];\n this.moved = false;\n // Grabbing the map stops any running animation (inertia, wheel zoom, easeTo)\n this.wheel.pending = 0;\n this.map.animate(undefined);\n }\n\n private move(e: PointerEvent): void {\n const point = this.local(e);\n const p = this.pointers.get(e.pointerId);\n\n if (!p) {\n if (e.pointerType === 'mouse') this.map.hover(point);\n\n return;\n }\n\n const [dx, dy] = [point[0] - p.point[0], point[1] - p.point[1]];\n\n if (Math.hypot(point[0] - p.start[0], point[1] - p.start[1]) > CLICK_TOLERANCE) this.moved = true;\n\n const eye = this.map.firstPerson;\n\n if (eye) {\n // At street level the drag turns the eye, the scene following the pointer as if grabbed\n const degrees = eye.fov / Math.max(1, this.map.canvas.clientHeight);\n\n this.map.setFirstPerson({ ...eye, bearing: eye.bearing - dx * degrees, pitch: eye.pitch + dy * degrees });\n p.point = point;\n\n return;\n }\n\n const engine = this.map.engine;\n const other = [...this.pointers.values()].find((q) => q !== p);\n\n if (this.pointers.size === 2 && other) {\n // Pinch: zoom by the change of spread, turn by the change of angle, pan by the midpoint\n const before = Math.hypot(p.point[0] - other.point[0], p.point[1] - other.point[1]);\n const after = Math.hypot(point[0] - other.point[0], point[1] - other.point[1]);\n const angle = (q: Point) => Math.atan2(q[1] - other.point[1], q[0] - other.point[0]);\n const mid = (q: Point): Point => [(q[0] + other.point[0]) / 2, (q[1] + other.point[1]) / 2];\n\n engine.pan(...mid(p.point), ...mid(point));\n if (before > 0 && after > 0) engine.zoomAt(Math.log2(after / before), ...mid(point));\n engine.rotate((-(angle(point) - angle(p.point)) * 180) / Math.PI, 0);\n } else if (p.rotate) {\n engine.rotate(-dx * ROTATE_RATE, -dy * ROTATE_RATE);\n } else {\n engine.pan(p.point[0], p.point[1], point[0], point[1]);\n this.trail.push([e.timeStamp, dx, dy]);\n }\n p.point = point;\n this.map.requestRender();\n }\n\n private up(e: PointerEvent): void {\n const p = this.pointers.get(e.pointerId);\n\n if (!p) return;\n this.pointers.delete(e.pointerId);\n // The next frame sends 'moveend' if the camera stays\n this.map.requestRender();\n if (!this.moved && e.type === 'pointerup' && p.button === 0 && this.pointers.size === 0) {\n this.map.emit('click', { point: p.point, lonLat: this.map.unproject(p.point) });\n\n return;\n }\n if (!p.rotate && this.pointers.size === 0 && !this.map.firstPerson) this.inertia(e.timeStamp, p.point);\n }\n\n /** Keeps panning at the release speed (last 50 ms), decaying exponentially */\n private inertia(now: number, from: Point): void {\n const recent = this.trail.filter(([t]) => now - t < 50);\n const first = recent[0];\n\n if (!first || recent.length < 2) return;\n\n const span = Math.max(16, now - first[0]);\n let vx = recent.reduce((s, [, dx]) => s + dx, 0) / span;\n let vy = recent.reduce((s, [, , dy]) => s + dy, 0) / span;\n\n if (Math.hypot(vx, vy) < 0.1) return;\n\n let last = performance.now();\n let point = from;\n\n this.map.animate((t) => {\n const dt = Math.min(64, t - last);\n\n last = t;\n\n const decay = Math.exp(-dt / INERTIA_DECAY);\n const next: Point = [point[0] + vx * dt, point[1] + vy * dt];\n\n this.map.engine.pan(point[0], point[1], next[0], next[1]);\n point = next;\n vx *= decay;\n vy *= decay;\n\n return Math.hypot(vx, vy) > 0.02;\n });\n }\n\n private onWheel(e: WheelEvent): void {\n e.preventDefault();\n\n // Lines (Firefox mouse wheels) are about 33 px\n const pixels = e.deltaMode === 1 ? e.deltaY * 33 : e.deltaY;\n const eye = this.map.firstPerson;\n\n if (eye) {\n // At street level: a narrower or wider field of view\n this.map.setFirstPerson({ ...eye, fov: eye.fov * Math.exp(pixels * 0.001) });\n\n return;\n }\n this.zoomBy(clamp(-pixels * WHEEL_RATE, -1, 1), this.local(e), e.deltaMode === 0 && Math.abs(pixels) < 40);\n }\n\n private onKey(e: KeyboardEvent): void {\n if (e.defaultPrevented || e.ctrlKey || e.metaKey || e.altKey || editable(e.target)) return;\n\n const action = keyAction(e.key, e.shiftKey);\n\n if (!action) return;\n e.preventDefault();\n\n const eye = this.map.firstPerson;\n\n if (eye) {\n // At street level the arrows turn the eye\n const turn = { ArrowLeft: [-10, 0], ArrowRight: [10, 0], ArrowUp: [0, 10], ArrowDown: [0, -10] }[e.key];\n\n if (turn)\n this.map.setFirstPerson({ ...eye, bearing: eye.bearing + (turn[0] ?? 0), pitch: eye.pitch + (turn[1] ?? 0) });\n\n return;\n }\n this.wheel.pending = 0;\n\n const reduced = typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n this.map.easeTo(keyCamera(action, this.map.getCamera()), reduced ? 0 : KEY_DURATION);\n }\n\n /** Smooth zoom around a screen point; touchpads (`direct`) follow the fingers without easing */\n private zoomBy(delta: number, at: Point, direct = false): void {\n if (direct) {\n this.map.engine.zoomAt(delta, at[0], at[1]);\n this.map.requestRender();\n\n return;\n }\n // Accumulate: a second notch before the end of the first one adds to it\n this.wheel.pending += delta;\n this.wheel.at = at;\n this.map.animate(() => {\n const step = Math.abs(this.wheel.pending) < 0.002 ? this.wheel.pending : this.wheel.pending * WHEEL_EASE;\n\n this.wheel.pending -= step;\n this.map.engine.zoomAt(step, this.wheel.at[0], this.wheel.at[1]);\n\n return this.wheel.pending !== 0;\n });\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"interaction.js","sourceRoot":"","sources":["../../src/ui/interaction.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Mouse, touch and keyboard controls. Every gesture only updates the camera and asks for a frame: the engine draws at most\n * once per display refresh, whatever the event rate of the device.\n */\n\nimport type { GeoMap } from '../map.ts';\nimport type { Point } from '../types.ts';\nimport { latitude, mercatorX, mercatorY, RAD } from '../util/geo.ts';\nimport { clamp } from '../util/math.ts';\nimport type { Camera } from '../wasm/isard.js';\n\n/** Zoom levels per wheel pixel (a mouse notch is about 100 px: 1/3 of a level) */\nconst WHEEL_RATE = 1 / 300;\n/** Share of the remaining wheel zoom applied per frame (smooth, about 150 ms to settle) */\nconst WHEEL_EASE = 0.3;\n/** Degrees per pixel when rotating or tilting with the mouse */\nconst ROTATE_RATE = 0.4;\n/** Degrees of tilt per CSS pixel two fingers move up or down together (MapLibre's rate) */\nconst TOUCH_PITCH_RATE = 0.5;\n/** CSS pixels a finger moves before a two-finger gesture is told: a tilt or a pinch */\nconst GESTURE_THRESHOLD = 6;\n/** A press that moves less than this (CSS pixels) is a click */\nconst CLICK_TOLERANCE = 4;\n/** Pan speed kept on release, decaying with this time constant (ms) */\nconst INERTIA_DECAY = 280;\n\n/** CSS pixels per arrow key press */\nconst KEY_PAN = 100;\n/** Degrees per Shift + left or right arrow */\nconst KEY_BEARING = 15;\n/** Degrees per Shift + up or down arrow */\nconst KEY_PITCH = 10;\n/** Duration of the moves made by keys, milliseconds */\nconst KEY_DURATION = 300;\n\n/** What a key does to the camera: a pan in CSS pixels, a zoom, rotation or tilt step, or facing north */\nexport type KeyAction = { pan: Point } | { zoom: number } | { bearing: number } | { pitch: number } | { reset: true };\n\n/** The action of a key (`KeyboardEvent.key`), as MapLibre's: arrows pan (with Shift: rotate and tilt), + and - zoom\n * (with Shift: two levels), 0 faces north and levels the view */\nexport const keyAction = (key: string, shift: boolean): KeyAction | undefined => {\n switch (key) {\n case 'ArrowLeft':\n return shift ? { bearing: -KEY_BEARING } : { pan: [-KEY_PAN, 0] };\n case 'ArrowRight':\n return shift ? { bearing: KEY_BEARING } : { pan: [KEY_PAN, 0] };\n case 'ArrowUp':\n return shift ? { pitch: KEY_PITCH } : { pan: [0, -KEY_PAN] };\n case 'ArrowDown':\n return shift ? { pitch: -KEY_PITCH } : { pan: [0, KEY_PAN] };\n case '+':\n case '=':\n return { zoom: shift ? 2 : 1 };\n case '-':\n case '_':\n return { zoom: shift ? -2 : -1 };\n case '0':\n return { reset: true };\n default:\n return undefined;\n }\n};\n\n/** The camera after a key's action: a pan moves the center by that many CSS pixels on screen (the ground in view,\n * turned with the bearing, stretched by the tilt) */\nexport const keyCamera = (action: KeyAction, camera: Camera): Partial<Camera> => {\n if ('zoom' in action) return { zoom: camera.zoom + action.zoom };\n if ('bearing' in action) return { bearing: camera.bearing + action.bearing };\n if ('pitch' in action) return { pitch: Math.max(0, camera.pitch + action.pitch) };\n if ('reset' in action) return { bearing: 0, pitch: 0 };\n\n const b = camera.bearing * RAD;\n const [sx, sy] = [action.pan[0], action.pan[1] / Math.max(0.25, Math.cos(camera.pitch * RAD))];\n // Web Mercator units (0 to 1 across the world, y down); the world is 512 CSS pixels at zoom 0\n const world = 512 * 2 ** camera.zoom;\n const dx = (sx * Math.cos(b) - sy * Math.sin(b)) / world;\n const dy = (sx * Math.sin(b) + sy * Math.cos(b)) / world;\n const [lon, lat] = camera.center;\n const x = mercatorX(lon) + dx;\n const y = clamp(mercatorY(lat) + dy, 0, 1);\n const wrapped = ((((x * 360) % 360) + 360) % 360) - 180;\n\n return { center: [wrapped, latitude(y)] };\n};\n\n/** An element that takes the keys typed in it */\nconst editable = (target: EventTarget | null): boolean => {\n if (!(target instanceof HTMLElement)) return false;\n\n return target.isContentEditable || ['INPUT', 'TEXTAREA', 'SELECT'].includes(target.tagName);\n};\n\ninterface Pointer {\n point: Point;\n start: Point;\n button: number;\n rotate: boolean;\n /** How far it moved since the two-finger gesture began (CSS pixels) */\n moved: Point;\n}\n\n/**\n * What two fingers do, once both moved (or one far, alone): a tilt if they lie side by side and both move up or down\n * together (as MapLibre and Google Earth take it), else a pinch (zoom, turn, pan); undefined before. A touch screen\n * sends the fingers' moves one after the other: the first one alone tells nothing yet\n */\nconst twoFingerGesture = (a: Pointer, b: Pointer): 'tilt' | 'pinch' | undefined => {\n const [ma, mb] = [Math.hypot(...a.moved), Math.hypot(...b.moved)];\n const [most, least] = [Math.max(ma, mb), Math.min(ma, mb)];\n\n if (most < GESTURE_THRESHOLD) return undefined;\n if (least < GESTURE_THRESHOLD / 2 && most < 2 * GESTURE_THRESHOLD) return undefined;\n\n const sideBySide = Math.abs(a.point[1] - b.point[1]) < Math.abs(a.point[0] - b.point[0]);\n const vertical = (q: Pointer) => Math.abs(q.moved[1]) > 2 * Math.abs(q.moved[0]);\n const together = Math.sign(a.moved[1]) === Math.sign(b.moved[1]);\n const both = Math.min(Math.abs(a.moved[1]), Math.abs(b.moved[1])) >= GESTURE_THRESHOLD / 2;\n\n return sideBySide && vertical(a) && vertical(b) && together && both ? 'tilt' : 'pinch';\n};\n\nexport class Interaction {\n private readonly pointers = new Map<number, Pointer>();\n private readonly cleanup: (() => void)[] = [];\n private wheel: { pending: number; at: Point } = { pending: 0, at: [0, 0] };\n /** What the two fingers on the map do, once told (`twoFingerGesture`) */\n private gesture: 'tilt' | 'pinch' | undefined;\n /** Recent pan moves, for the release speed: [time, dx, dy] */\n private trail: [number, number, number][] = [];\n private moved = false;\n /** The canvas's place on the page, read once: reading it on every pointer move would force a layout each time.\n * Read again after a resize, a scroll, and when a pointer comes in or goes down */\n private rect: DOMRect | undefined;\n /** A double click zooms in (Shift: out); off while the page takes double clicks (ending a drawing) */\n doubleClickZoom = true;\n /** A drag that turns and tilts goes around what is under the pointer where it starts (else around the center) */\n rotateAroundPointer = true;\n\n constructor(\n private readonly map: GeoMap,\n options: { keyboard?: boolean } = {},\n ) {\n const canvas = map.canvas;\n const listen = <K extends keyof HTMLElementEventMap>(\n type: K,\n handler: (e: HTMLElementEventMap[K]) => void,\n options?: AddEventListenerOptions,\n ) => {\n canvas.addEventListener(type, handler, options);\n this.cleanup.push(() => canvas.removeEventListener(type, handler));\n };\n const moved = () => {\n this.rect = undefined;\n };\n\n listen('pointerenter', moved);\n // Scrolls of the page or of any element holding the map\n if (typeof addEventListener === 'function') {\n addEventListener('scroll', moved, { capture: true, passive: true });\n this.cleanup.push(() => removeEventListener('scroll', moved, { capture: true }));\n }\n this.cleanup.push(map.on('resize', moved));\n listen('pointerdown', (e) => {\n this.rect = undefined;\n this.down(e);\n });\n listen('pointermove', (e) => this.move(e));\n listen('pointerup', (e) => this.up(e));\n listen('pointercancel', (e) => this.up(e));\n listen('pointerleave', (e) => {\n if (e.pointerType !== 'mouse') return;\n map.hover(undefined);\n map.emit('leave', {});\n });\n\n // On the container, the wheel zooms over markers and popups too\n const container = map.getContainer();\n const wheel = (e: WheelEvent) => this.onWheel(e);\n\n container.addEventListener('wheel', wheel, { passive: false });\n this.cleanup.push(() => container.removeEventListener('wheel', wheel));\n listen('dblclick', (e) => {\n if (this.doubleClickZoom && !this.map.firstPerson) this.zoomBy(e.shiftKey ? -1 : 1, this.local(e));\n });\n listen('contextmenu', (e) => e.preventDefault());\n if (options.keyboard ?? true) {\n // On the container: the keys work with the focus on a marker or a control too\n const key = (e: KeyboardEvent) => this.onKey(e);\n\n container.addEventListener('keydown', key);\n this.cleanup.push(() => container.removeEventListener('keydown', key));\n }\n }\n\n destroy(): void {\n this.cleanup.forEach((off) => {\n off();\n });\n }\n\n /** A gesture holds the map (pointers down): the camera has not stopped moving */\n get active(): boolean {\n return this.pointers.size > 0;\n }\n\n private local(e: MouseEvent): Point {\n this.rect ??= this.map.canvas.getBoundingClientRect();\n\n return [e.clientX - this.rect.left, e.clientY - this.rect.top];\n }\n\n private down(e: PointerEvent): void {\n this.map.canvas.setPointerCapture(e.pointerId);\n\n const point = this.local(e);\n const rotate = e.button === 2 || e.ctrlKey || e.shiftKey;\n\n this.pointers.set(e.pointerId, { point, start: point, button: e.button, rotate, moved: [0, 0] });\n // A new gesture: told again from here\n this.gesture = undefined;\n this.pointers.forEach((q) => {\n q.moved = [0, 0];\n });\n // A turn goes around what the pointer grabbed (a roof, a mesh, the relief); a pinch around the center\n if (rotate && this.rotateAroundPointer && this.pointers.size === 1 && !this.map.firstPerson) {\n this.map.engine.setPivot(...point);\n } else {\n this.map.engine.clearPivot();\n }\n this.trail = [];\n this.moved = false;\n // Grabbing the map stops any running animation (inertia, wheel zoom, easeTo)\n this.wheel.pending = 0;\n this.map.animate(undefined);\n }\n\n private move(e: PointerEvent): void {\n const point = this.local(e);\n const p = this.pointers.get(e.pointerId);\n\n if (!p) {\n if (e.pointerType === 'mouse') this.map.hover(point);\n\n return;\n }\n\n const [dx, dy] = [point[0] - p.point[0], point[1] - p.point[1]];\n\n if (Math.hypot(point[0] - p.start[0], point[1] - p.start[1]) > CLICK_TOLERANCE) this.moved = true;\n\n const eye = this.map.firstPerson;\n\n if (eye) {\n // At street level the drag turns the eye, the scene following the pointer as if grabbed\n const degrees = eye.fov / Math.max(1, this.map.canvas.clientHeight);\n\n this.map.setFirstPerson({ ...eye, bearing: eye.bearing - dx * degrees, pitch: eye.pitch + dy * degrees });\n p.point = point;\n\n return;\n }\n\n const engine = this.map.engine;\n const other = [...this.pointers.values()].find((q) => q !== p);\n\n p.moved = [p.moved[0] + dx, p.moved[1] + dy];\n if (this.pointers.size === 2 && other) this.gesture ??= twoFingerGesture(p, other);\n if (this.pointers.size === 2 && this.gesture === 'tilt') {\n // Both fingers up or down: the midpoint moves by half of this one's move\n engine.rotate(0, (-dy / 2) * TOUCH_PITCH_RATE);\n } else if (this.pointers.size === 2 && other && this.gesture === 'pinch') {\n // Pinch: zoom by the change of spread, turn by the change of angle, pan by the midpoint\n const before = Math.hypot(p.point[0] - other.point[0], p.point[1] - other.point[1]);\n const after = Math.hypot(point[0] - other.point[0], point[1] - other.point[1]);\n const angle = (q: Point) => Math.atan2(q[1] - other.point[1], q[0] - other.point[0]);\n const mid = (q: Point): Point => [(q[0] + other.point[0]) / 2, (q[1] + other.point[1]) / 2];\n\n engine.pan(...mid(p.point), ...mid(point));\n if (before > 0 && after > 0) engine.zoomAt(Math.log2(after / before), ...mid(point));\n engine.rotate((-(angle(point) - angle(p.point)) * 180) / Math.PI, 0);\n } else if (this.pointers.size === 2) {\n // Two fingers whose gesture is not told yet: a few pixels left out\n } else if (p.rotate) {\n engine.rotate(-dx * ROTATE_RATE, -dy * ROTATE_RATE);\n } else {\n engine.pan(p.point[0], p.point[1], point[0], point[1]);\n this.trail.push([e.timeStamp, dx, dy]);\n }\n p.point = point;\n this.map.requestRender();\n }\n\n private up(e: PointerEvent): void {\n const p = this.pointers.get(e.pointerId);\n\n if (!p) return;\n this.pointers.delete(e.pointerId);\n this.gesture = undefined;\n if (p.rotate) this.map.engine.clearPivot();\n // The next frame sends 'moveend' if the camera stays\n this.map.requestRender();\n if (!this.moved && e.type === 'pointerup' && p.button === 0 && this.pointers.size === 0) {\n this.map.emit('click', { point: p.point, lonLat: this.map.unproject(p.point) });\n\n return;\n }\n if (!p.rotate && this.pointers.size === 0 && !this.map.firstPerson) this.inertia(e.timeStamp, p.point);\n }\n\n /** Keeps panning at the release speed (last 50 ms), decaying exponentially */\n private inertia(now: number, from: Point): void {\n const recent = this.trail.filter(([t]) => now - t < 50);\n const first = recent[0];\n\n if (!first || recent.length < 2) return;\n\n const span = Math.max(16, now - first[0]);\n let vx = recent.reduce((s, [, dx]) => s + dx, 0) / span;\n let vy = recent.reduce((s, [, , dy]) => s + dy, 0) / span;\n\n if (Math.hypot(vx, vy) < 0.1) return;\n\n let last = performance.now();\n let point = from;\n\n this.map.animate((t) => {\n const dt = Math.min(64, t - last);\n\n last = t;\n\n const decay = Math.exp(-dt / INERTIA_DECAY);\n const next: Point = [point[0] + vx * dt, point[1] + vy * dt];\n\n this.map.engine.pan(point[0], point[1], next[0], next[1]);\n point = next;\n vx *= decay;\n vy *= decay;\n\n return Math.hypot(vx, vy) > 0.02;\n });\n }\n\n private onWheel(e: WheelEvent): void {\n e.preventDefault();\n\n // Lines (Firefox mouse wheels) are about 33 px\n const pixels = e.deltaMode === 1 ? e.deltaY * 33 : e.deltaY;\n const eye = this.map.firstPerson;\n\n if (eye) {\n // At street level: a narrower or wider field of view\n this.map.setFirstPerson({ ...eye, fov: eye.fov * Math.exp(pixels * 0.001) });\n\n return;\n }\n this.zoomBy(clamp(-pixels * WHEEL_RATE, -1, 1), this.local(e), e.deltaMode === 0 && Math.abs(pixels) < 40);\n }\n\n private onKey(e: KeyboardEvent): void {\n if (e.defaultPrevented || e.ctrlKey || e.metaKey || e.altKey || editable(e.target)) return;\n\n const action = keyAction(e.key, e.shiftKey);\n\n if (!action) return;\n e.preventDefault();\n\n const eye = this.map.firstPerson;\n\n if (eye) {\n // At street level the arrows turn the eye\n const turn = { ArrowLeft: [-10, 0], ArrowRight: [10, 0], ArrowUp: [0, 10], ArrowDown: [0, -10] }[e.key];\n\n if (turn)\n this.map.setFirstPerson({ ...eye, bearing: eye.bearing + (turn[0] ?? 0), pitch: eye.pitch + (turn[1] ?? 0) });\n\n return;\n }\n this.wheel.pending = 0;\n\n const reduced = typeof matchMedia === 'function' && matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n this.map.easeTo(keyCamera(action, this.map.getCamera()), reduced ? 0 : KEY_DURATION);\n }\n\n /** Smooth zoom around a screen point; touchpads (`direct`) follow the fingers without easing */\n private zoomBy(delta: number, at: Point, direct = false): void {\n if (direct) {\n this.map.engine.zoomAt(delta, at[0], at[1]);\n this.map.requestRender();\n\n return;\n }\n // Accumulate: a second notch before the end of the first one adds to it\n this.wheel.pending += delta;\n this.wheel.at = at;\n this.map.animate(() => {\n const step = Math.abs(this.wheel.pending) < 0.002 ? this.wheel.pending : this.wheel.pending * WHEEL_EASE;\n\n this.wheel.pending -= step;\n this.map.engine.zoomAt(step, this.wheel.at[0], this.wheel.at[1]);\n\n return this.wheel.pending !== 0;\n });\n }\n}\n"]}
|
package/dist/wasm/isard.d.ts
CHANGED
|
@@ -425,6 +425,10 @@ export class Engine {
|
|
|
425
425
|
* Removes the panorama
|
|
426
426
|
*/
|
|
427
427
|
clearPanorama(): void;
|
|
428
|
+
/**
|
|
429
|
+
* The turns go around the screen center again
|
|
430
|
+
*/
|
|
431
|
+
clearPivot(): void;
|
|
428
432
|
/**
|
|
429
433
|
* Stops loading the tiles of the flight's destination (`preload`)
|
|
430
434
|
*/
|
|
@@ -554,7 +558,7 @@ export class Engine {
|
|
|
554
558
|
*/
|
|
555
559
|
resize(width: number, height: number, pixel_ratio: number): void;
|
|
556
560
|
/**
|
|
557
|
-
* Turns and tilts around the
|
|
561
|
+
* Turns and tilts, in degrees: around the pivot if one is set (`setPivot`), else around the screen center
|
|
558
562
|
*/
|
|
559
563
|
rotate(bearing: number, pitch: number): void;
|
|
560
564
|
/**
|
|
@@ -816,6 +820,12 @@ export class Engine {
|
|
|
816
820
|
* shader fails to compile (the error carries its info log)
|
|
817
821
|
*/
|
|
818
822
|
setPanorama(lon: number, lat: number, height: number, rotation: Float64Array, cameras: Float64Array, radius: number, opacity: number): void;
|
|
823
|
+
/**
|
|
824
|
+
* Sets the point the next turns and tilts go around (`rotate`): what is drawn under a screen point (CSS
|
|
825
|
+
* pixels), a roof or a mesh as the relief. Read back from the last frame (a stall): once, where a drag starts.
|
|
826
|
+
* Returns whether something was drawn there; over nothing, the turns go around the center
|
|
827
|
+
*/
|
|
828
|
+
setPivot(x: number, y: number): boolean;
|
|
819
829
|
/**
|
|
820
830
|
* The style of a point cloud: 14 numbers (see `Style::parse`), the colors of the 256 classes (RGBA,
|
|
821
831
|
* alpha 0 hides a class) and the ramp of the altitudes (256 RGBA texels)
|
|
@@ -888,6 +898,10 @@ export class Engine {
|
|
|
888
898
|
* it, tiles are decoded on the main thread. Set it before adding 3D Tiles layers.
|
|
889
899
|
*/
|
|
890
900
|
setTileLoader(loader: TileLoaderLike | null): void;
|
|
901
|
+
/**
|
|
902
|
+
* Whether the walls of a 3D Tiles layer's untextured meshes show their windows: glass by day, some lit at night
|
|
903
|
+
*/
|
|
904
|
+
setTiles3dFacades(id: number, facades: boolean): void;
|
|
891
905
|
/**
|
|
892
906
|
* Screen-space error threshold, opacity, size of the points (CSS pixels, 2 if not given) and color (RGB 0-1, empty
|
|
893
907
|
* for none: it tints the textures and colors the untextured meshes) of a 3D Tiles layer
|
|
@@ -1078,6 +1092,7 @@ export interface InitOutput {
|
|
|
1078
1092
|
readonly engine_bounds: (a: number) => [number, number];
|
|
1079
1093
|
readonly engine_camera: (a: number) => any;
|
|
1080
1094
|
readonly engine_clearPanorama: (a: number) => void;
|
|
1095
|
+
readonly engine_clearPivot: (a: number) => void;
|
|
1081
1096
|
readonly engine_clearPreload: (a: number) => void;
|
|
1082
1097
|
readonly engine_clearViewshed: (a: number) => void;
|
|
1083
1098
|
readonly engine_customMatrix: (a: number, b: number, c: number) => [number, number];
|
|
@@ -1149,6 +1164,7 @@ export interface InitOutput {
|
|
|
1149
1164
|
readonly engine_setNetworkValues: (a: number, b: number, c: number, d: number) => void;
|
|
1150
1165
|
readonly engine_setPanorama: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number) => [number, number];
|
|
1151
1166
|
readonly engine_setPanoramaImage: (a: number, b: number, c: any) => [number, number];
|
|
1167
|
+
readonly engine_setPivot: (a: number, b: number, c: number) => number;
|
|
1152
1168
|
readonly engine_setPointCloudStyle: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => void;
|
|
1153
1169
|
readonly engine_setRasterStyle: (a: number, b: number, c: number, d: number) => void;
|
|
1154
1170
|
readonly engine_setRequestHeaders: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
|
@@ -1159,6 +1175,7 @@ export interface InitOutput {
|
|
|
1159
1175
|
readonly engine_setSymbols: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number) => [number, number];
|
|
1160
1176
|
readonly engine_setTerrain: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => [number, number];
|
|
1161
1177
|
readonly engine_setTileLoader: (a: number, b: any) => void;
|
|
1178
|
+
readonly engine_setTiles3dFacades: (a: number, b: number, c: number) => void;
|
|
1162
1179
|
readonly engine_setTiles3dStyle: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => void;
|
|
1163
1180
|
readonly engine_setVectorSublayers: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number, q: number, r: number, s: number, t: number, u: number, v: number) => void;
|
|
1164
1181
|
readonly engine_setVectorTile: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number, q: number, r: number, s: number, t: number, u: number, v: number, w: number, x: number, y: number, z: number, a1: number, b1: number, c1: number, d1: number, e1: number, f1: number, g1: number) => [number, number];
|
package/dist/wasm/isard.js
CHANGED
|
@@ -361,6 +361,12 @@ export class Engine {
|
|
|
361
361
|
clearPanorama() {
|
|
362
362
|
wasm.engine_clearPanorama(this.__wbg_ptr);
|
|
363
363
|
}
|
|
364
|
+
/**
|
|
365
|
+
* The turns go around the screen center again
|
|
366
|
+
*/
|
|
367
|
+
clearPivot() {
|
|
368
|
+
wasm.engine_clearPivot(this.__wbg_ptr);
|
|
369
|
+
}
|
|
364
370
|
/**
|
|
365
371
|
* Stops loading the tiles of the flight's destination (`preload`)
|
|
366
372
|
*/
|
|
@@ -640,7 +646,7 @@ export class Engine {
|
|
|
640
646
|
wasm.engine_resize(this.__wbg_ptr, width, height, pixel_ratio);
|
|
641
647
|
}
|
|
642
648
|
/**
|
|
643
|
-
* Turns and tilts around the
|
|
649
|
+
* Turns and tilts, in degrees: around the pivot if one is set (`setPivot`), else around the screen center
|
|
644
650
|
* @param {number} bearing
|
|
645
651
|
* @param {number} pitch
|
|
646
652
|
*/
|
|
@@ -1268,6 +1274,18 @@ export class Engine {
|
|
|
1268
1274
|
throw takeFromExternrefTable0(ret[0]);
|
|
1269
1275
|
}
|
|
1270
1276
|
}
|
|
1277
|
+
/**
|
|
1278
|
+
* Sets the point the next turns and tilts go around (`rotate`): what is drawn under a screen point (CSS
|
|
1279
|
+
* pixels), a roof or a mesh as the relief. Read back from the last frame (a stall): once, where a drag starts.
|
|
1280
|
+
* Returns whether something was drawn there; over nothing, the turns go around the center
|
|
1281
|
+
* @param {number} x
|
|
1282
|
+
* @param {number} y
|
|
1283
|
+
* @returns {boolean}
|
|
1284
|
+
*/
|
|
1285
|
+
setPivot(x, y) {
|
|
1286
|
+
const ret = wasm.engine_setPivot(this.__wbg_ptr, x, y);
|
|
1287
|
+
return ret !== 0;
|
|
1288
|
+
}
|
|
1271
1289
|
/**
|
|
1272
1290
|
* The style of a point cloud: 14 numbers (see `Style::parse`), the colors of the 256 classes (RGBA,
|
|
1273
1291
|
* alpha 0 hides a class) and the ramp of the altitudes (256 RGBA texels)
|
|
@@ -1439,6 +1457,14 @@ export class Engine {
|
|
|
1439
1457
|
setTileLoader(loader) {
|
|
1440
1458
|
wasm.engine_setTileLoader(this.__wbg_ptr, loader);
|
|
1441
1459
|
}
|
|
1460
|
+
/**
|
|
1461
|
+
* Whether the walls of a 3D Tiles layer's untextured meshes show their windows: glass by day, some lit at night
|
|
1462
|
+
* @param {number} id
|
|
1463
|
+
* @param {boolean} facades
|
|
1464
|
+
*/
|
|
1465
|
+
setTiles3dFacades(id, facades) {
|
|
1466
|
+
wasm.engine_setTiles3dFacades(this.__wbg_ptr, id, facades);
|
|
1467
|
+
}
|
|
1442
1468
|
/**
|
|
1443
1469
|
* Screen-space error threshold, opacity, size of the points (CSS pixels, 2 if not given) and color (RGB 0-1, empty
|
|
1444
1470
|
* for none: it tints the textures and colors the untextured meshes) of a 3D Tiles layer
|
|
@@ -3129,7 +3155,7 @@ function __wbg_get_imports() {
|
|
|
3129
3155
|
return ret;
|
|
3130
3156
|
},
|
|
3131
3157
|
__wbindgen_generic_0000000000000001: function(arg0, arg1) {
|
|
3132
|
-
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx:
|
|
3158
|
+
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 229, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
|
|
3133
3159
|
const ret = makeMutClosure(arg0, arg1, wasm_bindgen_2e566c63402fe7fa___convert__closures_____invoke___wasm_bindgen_2e566c63402fe7fa___JsValue__core_37ee0ce0c4cd57d5___result__Result_____wasm_bindgen_2e566c63402fe7fa___JsError___true_);
|
|
3134
3160
|
return ret;
|
|
3135
3161
|
},
|
|
@@ -184,6 +184,10 @@ export class Engine {
|
|
|
184
184
|
* The camera as set or moved: center (degrees), zoom, pitch and bearing (degrees)
|
|
185
185
|
*/
|
|
186
186
|
camera(): Camera;
|
|
187
|
+
/**
|
|
188
|
+
* The turns go around the screen center again
|
|
189
|
+
*/
|
|
190
|
+
clearPivot(): void;
|
|
187
191
|
/**
|
|
188
192
|
* Stops loading the tiles of the flight's destination (`preload`)
|
|
189
193
|
*/
|
|
@@ -300,7 +304,7 @@ export class Engine {
|
|
|
300
304
|
*/
|
|
301
305
|
resize(width: number, height: number, pixel_ratio: number): void;
|
|
302
306
|
/**
|
|
303
|
-
* Turns and tilts around the
|
|
307
|
+
* Turns and tilts, in degrees: around the pivot if one is set (`setPivot`), else around the screen center
|
|
304
308
|
*/
|
|
305
309
|
rotate(bearing: number, pitch: number): void;
|
|
306
310
|
/**
|
|
@@ -527,6 +531,12 @@ export class Engine {
|
|
|
527
531
|
* One value per node; negative = unreached
|
|
528
532
|
*/
|
|
529
533
|
setNetworkValues(id: number, values: Float32Array): void;
|
|
534
|
+
/**
|
|
535
|
+
* Sets the point the next turns and tilts go around (`rotate`): what is drawn under a screen point (CSS
|
|
536
|
+
* pixels), a roof or a mesh as the relief. Read back from the last frame (a stall): once, where a drag starts.
|
|
537
|
+
* Returns whether something was drawn there; over nothing, the turns go around the center
|
|
538
|
+
*/
|
|
539
|
+
setPivot(x: number, y: number): boolean;
|
|
530
540
|
/**
|
|
531
541
|
* Opacity and saturation (0-1) of a raster layer; nothing for another id
|
|
532
542
|
*/
|
|
@@ -739,6 +749,7 @@ export interface InitOutput {
|
|
|
739
749
|
readonly engine_addVectorTiles: (a: number) => [number, number, number];
|
|
740
750
|
readonly engine_bounds: (a: number) => [number, number];
|
|
741
751
|
readonly engine_camera: (a: number) => any;
|
|
752
|
+
readonly engine_clearPivot: (a: number) => void;
|
|
742
753
|
readonly engine_clearPreload: (a: number) => void;
|
|
743
754
|
readonly engine_clearViewshed: (a: number) => void;
|
|
744
755
|
readonly engine_customMatrix: (a: number, b: number, c: number) => [number, number];
|
|
@@ -802,6 +813,7 @@ export interface InitOutput {
|
|
|
802
813
|
readonly engine_setNetworkScales: (a: number, b: number, c: number, d: number) => void;
|
|
803
814
|
readonly engine_setNetworkStyle: (a: number, b: number, c: number, d: number) => void;
|
|
804
815
|
readonly engine_setNetworkValues: (a: number, b: number, c: number, d: number) => void;
|
|
816
|
+
readonly engine_setPivot: (a: number, b: number, c: number) => number;
|
|
805
817
|
readonly engine_setRasterStyle: (a: number, b: number, c: number, d: number) => void;
|
|
806
818
|
readonly engine_setRequestHeaders: (a: number, b: number, c: number, d: number, e: number, f: number, g: number) => void;
|
|
807
819
|
readonly engine_setSky: (a: number, b: number) => void;
|