WebGL Map (Minimal)
Minimal, dependency-light WebGL map that renders a single large raster with smooth pan and continuous zoom. Pixel CRS only (image pixel coordinates; no Web Mercator).
Status
- Early-stage, pre-release. Everything is subject to change before the initial release. Expect breaking changes as APIs and internals evolve.
Features
- WebGL single-image rendering
- Smooth pan and wheel/pinch zoom
- Pixel CRS: image pixel coordinates (no geodetic projection)
- WrapX support (disabled in Hagga Basin demo)
- Typed events for input, lifecycle, and per‑frame HUD (frame counter)
Documentation
- Guide:
docs/guide/README.md(concepts and how-tos) - API Reference:
docs/api/README.md(generated) - Quick index:
docs/API_OVERVIEW.md
Getting Started Run locally
- Install deps:
npm install - Start dev server:
npm run dev(SvelteKit app athttp://localhost:5173) - Open
/map. Pan with mouse drag; zoom with wheel or pinch (touch).
Files
apps/svelte-gtmap-test/src/routes/map/+page.svelte: Minimal usage in SvelteKit (/map).apps/noframework-gtmap-test/index.html: No‑framework demo (HTML + TS).apps/noframework-gtmap-test/src/main.ts: Plain TS usage and HUD wiring.packages/gtmap/src/api/map.ts: PublicGTMapfacade (typed API surface).packages/gtmap/src/internal/mapgl.ts: Core WebGL implementation (single-image renderer, input, cache).- Pixel CRS only: coordinates are image pixels (x, y) at native resolution.
Public API
- Import
GTMapvia@gaming.tools/gtmap(published) or@gtmap(Vite alias in demos).- Raster via
imageinMapOptions:{ url, width, height }plus optionalwrapXand view limits. - View with Transition Builder:
map.transition().center(...).zoom(...).apply({ animate? }). - Content:
addIcon,addMarker,addVector(oraddVectorslegacy batch). - Events:
map.events.on(name).each(h)andmap.events.once(name)(typed payloads). Includes pointer/mouse, lifecycle, frame, and map-level marker events (markerenter/leave/click/down/up/longpress). - In demos,
@gtmapis aliased to the local source for fast iteration.
- Raster via
Coordinate Transforms (world → pixels)
- Initialize once with your external/world bounds:
map.setCoordBounds({ minX, minY, maxX, maxY }). - Convert world points to image pixels:
map.translate(x, y, transform?). - Supported transforms:
'original' | 'flipVertical' | 'flipHorizontal' | 'flipBoth' | 'rotate90CW' | 'rotate90CCW' | 'rotate180'. - Mapping preserves aspect ratio and centers the bounds within the image.
See the full API reference in docs/api/README.md.
Demo apps
- SvelteKit:
apps/svelte-gtmap-test→ open/map - No‑framework:
apps/noframework-gtmap-test/index.html
Svelte Docs
- Svelte v5 docs are mirrored under
docs/svelte/. Use them as the source of truth (runes,onclick={...}, etc.).
Loading Indicator
On load, the map shows a small spinner and blocks rendering and input until the full‑resolution image is decoded and uploaded to the GPU. No preview image is rendered.
Customize the spinner via spinner in MapOptions:
size(px): outer diameter (default 32)thickness(px): ring width (default 3)color: active arc (defaultrgba(0,0,0,0.6))trackColor: background ring (defaultrgba(0,0,0,0.2))speedMs: rotation period (default 1000)
Visibility Control (suspend/resume)
If you render multiple maps, suspend offscreen ones to save CPU/network/VRAM:
// Suspend a map (stop RAF, input, and rendering)
map.setActive(false);
// Suspend and also release the WebGL context and VRAM
map.setActive(false, { releaseGL: true });
// Resume (recreates GL state if it was released)
map.setActive(true);This pairs well with IntersectionObserver or the Page Visibility API.
Image Source Hagga Basin (survival_1)
- URL:
https://gtcdn.info/dune/tiles/hb_8k.webp - Base resolution: 8192 × 8192 (set
minZoom/maxZoomto control view constraints) - Wrap: disabled (finite image; no world wrap)
- Note: Game map (not geo-referenced); renders as a finite raster.
Customization
- Center/zoom: Set when constructing
GTMapin the demos. - Zoom bounds:
minZoom/maxZoom. - Grid overlay:
setGridVisible(true|false). - Wheel speed:
setWheelSpeed(number). - Icon scaling:
setIconScaleFunction(fn|null)wherefn(zoom,min,max) -> scale(1.0 = screen‑fixed)
Notes and Next Steps
- Single raster currently; markers and vectors are simple overlays.
- Frame/HUD via
map.events.on('frame')(frame counter available).
Performance
- Full textures upload incrementally in small stripes with adaptive time budgets; uploads pause during interaction and resume when idle.
- Uses
createImageBitmapwhere available for off‑main‑thread decode; falls back to<img>. - Host via a static server for production; dev server is preferred.
Monorepo & Package Manager
- npm workspaces; see root
package.json. - Common commands:
- Install:
npm install - Dev server:
npm run dev - Build:
npm run build(builds Svelte app andpackages/gtmap) - Lint/format:
npm run lint,npm run format
- Install: