X-GIS

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.

XGISMap.getCamera

map.getCamera(): Camera

Returns 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.

XGISMap.setProjection

map.setProjection(name: string): void

Switch 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")

XGISMap.setSourceData

map.setSourceData(sourceId: string, data: GeoJSONFeatureCollection): void

Replace 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.

XGISMap.setGlyphsUrl

map.setGlyphsUrl(url: string | null): void

Set 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): void

Seed 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 Camera

Holds `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: Projection

Web Mercator (EPSG:3857). The default — used unless `setProjection` is called.

equirectangular

const equirectangular: Projection

Plate carrée — latitude maps directly to y.

naturalEarth

const naturalEarth: Projection

Pseudo-cylindrical, polynomial. Low-distortion world overview.

orthographic

orthographic(lon: number, lat: number): Projection

Globe view centered on (lon, lat). Hemispherical visibility, back-face culled.

getProjection

getProjection(name: string, ...args: number[]): Projection

Look 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): void

Wire 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 ComputeDispatcher

Helper around WebGPU compute pipelines. Wrap a WGSL compute shader + bind groups, then `dispatch(workgroups)` per frame.

createColorRampTexture

createColorRampTexture(device: GPUDevice, name: string): GPUTexture

Create 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>): DrawHandle

Add 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 },
})

DrawHandle

interface DrawHandle

Handle 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.

map.graphics.addImage

map.graphics.addImage(name: string, image: ImageBitmap | ImageData): void

Register 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).

Stats + diagnostics

Optional UI panel and underlying tracker for performance/diagnostic information.

StatsPanel

class StatsPanel

On-screen FPS / draw-call / triangle-count overlay. Mount once near the canvas; the panel polls live values from the shared StatsTracker.

StatsTracker

class StatsTracker

Singleton 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 HTMLElement

A `<x-gis-map src="…">` element. Fetches the .xgis source, mounts an XGISMap inside its shadow root, and reflects basic camera attributes.

registerXGISElement

registerXGISElement(): void

Call once during app bootstrap to register the `<x-gis-map>` custom element with the global registry.