Reference
JavaScript API.
The @xgis/runtime symbols
most apps use. Most only need XGISMap;
the barrel also exports lower-level loaders, sources, and capability tables
for advanced extension.
Runtime support
- WebGPUSupported— Chrome 113+ · Edge 113+ · Safari 18+ · Firefox 141+
- No WebGPUUnsupported— WebGPU is required — there is no Canvas 2D fallback. When no adapter is present the map shows an "unavailable" message (the host's onWebGPUUnavailable hook, or a default in-container notice) and does not render — no degraded mode.
- MobileLimited— iOS Safari 18+ · Android Chrome with WebGPU enabled. Heavier scenes may throttle.
- Web workersSupported— Required — used for off-main-thread MVT decode + GeoJSON tessellation.
Core
The map class is the only entry point most apps need.
XGISMap
new XGISMap(canvas: HTMLCanvasElement, options?: XGISMapOptions)Owns the GPU device, the camera, the renderers, and the source catalog. Construct once per canvas.
Parameters
| Name | Type | Description |
|---|---|---|
canvas | HTMLCanvasElement | Target canvas to render into. Must already be attached to the DOM — the constructor reads its `clientWidth` / `clientHeight` to size the WebGPU swap chain. |
options | XGISMapOptions | Optional bag: initial `center` / `zoom` / `bearing` / `pitch`, `projection`, `backend`, `glyphs`, `spriteUrl`, `fonts`, `sources`, and related knobs. Everything has a default — `new XGISMap(canvas)` alone is valid. |
Example
import { XGISMap } from "@xgis/runtime"const map = new XGISMap(canvas)await map.run(source, baseUrl)XGISMap.run
map.run(source: string, baseUrl: string): Promise<void>Compile the .xgis source string, resolve relative `url:` references against `baseUrl`, allocate GPU resources, and start the render loop. Resolves once the first frame is composed.
Parameters
| Name | Type | Description |
|---|---|---|
source | string | A valid `.xgis` source. Typically loaded via Vite's `?raw` import. |
baseUrl | string | Used to resolve relative `url:` references inside source blocks. Pass `"/"` when the assets sit at site root. |
Returns
Promise<void> — Resolves after WebGPU resources are allocated and the first frame is composed. Rejects if the source fails to compile or a required resource (e.g. PMTiles header) returns 4xx/5xx. See also
XGISMap.getCamera
map.getCamera(): CameraReturns the live camera. Mutate `.lon`, `.lat`, `.zoom`, `.bearing`, `.pitch` — the runtime picks up changes on the next frame.
Returns
Camera — The live camera instance — same object across calls, mutating it directly drives the next frame. See also
XGISMap.setProjection
map.setProjection(name: string): voidSwitch the active projection by name. No re-tessellation; a single uniform write flips Mercator → Orthographic → Natural Earth. An unknown name is dropped with a console warning and the current projection stays active.
Parameters
| Name | Type | Description |
|---|---|---|
name | string | Projection name. One of: mercator, equirectangular, natural_earth, orthographic, azimuthal_equidistant, stereographic, oblique_mercator. Note: getProjection() returns a CPU math-mirror record, NOT an argument to this method. |
Example
map.setProjection("orthographic")See also
XGISMap.setSourceData
map.setSourceData(sourceId: string, data: GeoJSONFeatureCollection): voidReplace the features of a GeoJSON source at runtime and retile. Use with an inline source declared without `url:` / `data:` (an empty placeholder the host fills), or to push fresh data into an existing GeoJSON source. Coalesces with `updateFeature` patches into one retile per source per frame.
Parameters
| Name | Type | Description |
|---|---|---|
sourceId | string | The `source` block id from the .xgis program. |
data | GeoJSONFeatureCollection | The replacement FeatureCollection. Reprojected from the source's declared CRS to WGS84 when one is set. |
See also
XGISMap.setGlyphsUrl
map.setGlyphsUrl(url: string | null): voidSet the style's `glyphs` URL template (e.g. `https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf`) used by the HTTP glyph provider for SDF text. Call before the first label-producing frame to pre-stage the URL; pass `null` to clear it.
Parameters
| Name | Type | Description |
|---|---|---|
url | string | null | A `{fontstack}` / `{range}` PBF URL template, or `null` to clear. |
XGISMap.setInlineGlyphs
map.setInlineGlyphs(seed: InlineGlyphs | null): voidSeed the glyph chain with pre-loaded PBF range bytes — keyed `{ fontstack: { rangeStart: Uint8Array } }`. Same chain semantics as `setGlyphsUrl`; for embedded / air-gapped deployments that ship glyph data inside their own bundle. Call before the first label frame.
Parameters
| Name | Type | Description |
|---|---|---|
seed | InlineGlyphs | null | Per-fontstack PBF range bytes, or `null` to clear. |
Camera
Direct camera control — most code interacts via the input controllers, not the camera class.
Camera
class CameraHolds `lon`, `lat`, `zoom`, `bearing`, `pitch`, plus derived MVP matrices. `zoomAt(delta, x, y, w, h)` zooms toward a screen-space point.
Projections
Seven projections in CPU-mirror form. Each returns a Projection record the runtime wires into the shader uniform.
mercator
const mercator: ProjectionWeb Mercator (EPSG:3857). The default — used unless `setProjection` is called.
equirectangular
const equirectangular: ProjectionPlate carrée — latitude maps directly to y.
naturalEarth
const naturalEarth: ProjectionPseudo-cylindrical, polynomial. Low-distortion world overview.
orthographic
orthographic(lon: number, lat: number): ProjectionGlobe view centered on (lon, lat). Hemispherical visibility, back-face culled.
getProjection
getProjection(name: string, ...args: number[]): ProjectionLook up a projection by name with optional center coordinates. Names: mercator, equirectangular, natural_earth, orthographic, azimuthal_equidistant, stereographic, oblique_mercator. Returns a CPU math-mirror record for projecting coordinates on the host side — it is NOT an argument to `map.setProjection`. To switch the map's active projection, call `map.setProjection("orthographic")` with the name string instead.
Example
import { getProjection } from "@xgis/runtime"// CPU-side projection math (e.g. placing a custom overlay):const proj = getProjection("orthographic", 127, 37.5)// Switching the map's active projection is by NAME, not this record:map.setProjection("orthographic")Loaders
Source-loading helpers used by the .xgis runtime under the hood. Most apps don't call these directly — declare a `source` block in the .xgis source instead.
loadGeoJSON
loadGeoJSON(url: string, baseUrl?: string): Promise<GeoJSON>Fetch a GeoJSON file. Resolves to the parsed FeatureCollection.
loadPMTilesSource
loadPMTilesSource(opts: PMTilesSourceOptions): Promise<TileSource>Construct a streaming PMTiles backend. Reads the archive header + vector_layers metadata via HTTP Range Requests; returns a TileSource that can be attached to a TileCatalog.
attachPMTilesSource
attachPMTilesSource(catalog: TileCatalog, source: TileSource): voidWire a PMTiles backend into a tile catalog. The .xgis `type: pmtiles` runtime handler does this for you.
lonLatToMercator
lonLatToMercator(lon: number, lat: number): [number, number]Project lon/lat to global Web Mercator meters. Useful for placing custom overlays at known coordinates.
GPU compute
Public compute infrastructure for advanced layer types (color ramps, vector field visualizations, etc.).
ComputeDispatcher
class ComputeDispatcherHelper around WebGPU compute pipelines. Wrap a WGSL compute shader + bind groups, then `dispatch(workgroups)` per frame.
createColorRampTexture
createColorRampTexture(device: GPUDevice, name: string): GPUTextureCreate a 1D color-ramp texture from a registered ramp name (viridis, magma, plasma, etc.). Sampled by gradient layers.
availableRamps
availableRamps(): string[]List the registered color ramp names — useful for building UI selectors.
Host graphics
The `map.graphics` façade — retained, geo-anchored batches that project on the GPU. Accessors run ONCE at add()/update() (never per frame), so a camera move rewrites only the frame uniform and the batch is N-independent. Register host sprite images here too.
map.graphics.add (arrow)
map.graphics.add<D>(spec: ArrowDrawSpec<D>): DrawHandleAdd a retained arrow batch — the movement vector-field glyph, a procedural oriented arrow mesh (no sprite). Per item: a geo anchor (the arrow tail), a bearing, a length, and a colour. Accessors are packed once at add(); the GPU buffers materialise immediately when a device exists, else on the next attachDevice.
Parameters
| Name | Type | Description |
|---|---|---|
type | 'arrow' | Discriminant selecting the arrow spec. |
data | readonly D[] | The per-item source array. Each accessor is run once over this array to pack a flat attribute buffer. |
getPosition | Packed<Position, D> | Geo anchor `[lon, lat]` in degrees (WGS84) — the arrow TAIL. The ONE required accessor. A constant packs one shared value; a `(d, index) => Position` function is run once per item. |
getBearing optional | Packed<number, D> | Geographic bearing the arrow points along, in degrees (0 = north, clockwise). Projected on the GPU from two geo points, so it stays correct under camera bearing / pitch / globe. Default 0 (north). |
getSize optional | Packed<number, D> | Arrow length in px (tail→tip). Default 1. |
getColor optional | Packed<IconColor, D> | Solid fill colour — a hex string (`#rrggbb` / `#rrggbbaa`) or an rgba tuple in 0..1. Default white. |
updateTriggers optional | Partial<Record<IconUpdateTrigger, unknown>> | Marks which attributes a later `update({ triggers })` will re-pack. Triggers: `position` | `color` | `size` | `rotation` | `image`. |
Returns
DrawHandle — A live handle to the batch — read `count`, re-pack accessors via `update({ triggers })`, or free the GPU buffers with `remove()`. Example
const handle = map.graphics.add({ type: "arrow", data: winds, getPosition: (w) => [w.lon, w.lat], getBearing: (w) => w.dirDeg, getSize: 24, getColor: "#3aa0ff", updateTriggers: { color: true },})See also
DrawHandle
interface DrawHandleHandle to a live retained batch, returned by `map.graphics.add`.
Parameters
| Name | Type | Description |
|---|---|---|
count | number | Items currently in the batch (read-only). 0 after `remove()`. |
update | (patch: { triggers: readonly IconUpdateTrigger[] }) => void | Re-run the named accessors and re-upload their attribute(s). `["color"]` re-uploads ONLY the tint buffer (one writeBuffer); any other trigger re-packs the feat buffer. It re-runs accessors on the FIXED data set — it never resizes (a size change is rejected with a warning; re-add the batch instead). |
remove | () => void | Remove the batch and free its GPU buffers. |
See also
map.graphics.addImage
map.graphics.addImage(name: string, image: ImageBitmap | ImageData): voidRegister a host sprite image into the atlas under `name` (Mapbox `map.addImage` parity). Register images BEFORE an icon batch's `add()` so their sprites resolve — a missing sprite packs an invisible instance and warns. Also reachable directly as `map.addImage`.
Parameters
| Name | Type | Description |
|---|---|---|
name | string | Registry key the icon spec's `getImage` accessor resolves against. |
image | ImageBitmap | ImageData | The decoded sprite bitmap. Host-only render, no eviction, bounded page (Phase-0 limitations). |
See also
Stats + diagnostics
Optional UI panel and underlying tracker for performance/diagnostic information.
StatsPanel
class StatsPanelOn-screen FPS / draw-call / triangle-count overlay. Mount once near the canvas; the panel polls live values from the shared StatsTracker.
StatsTracker
class StatsTrackerSingleton that the runtime feeds frame stats into. Read directly from custom UI when StatsPanel doesn't fit.
Custom element
Web Components wrapper for declarative usage in plain HTML.
XGISMapElement
class XGISMapElement extends HTMLElementA `<x-gis-map src="…">` element. Fetches the .xgis source, mounts an XGISMap inside its shadow root, and reflects basic camera attributes.
registerXGISElement
registerXGISElement(): voidCall once during app bootstrap to register the `<x-gis-map>` custom element with the global registry.
Problem on this page?