Caller-owned layer panels and map tools
Caller-owned UI reads public states and uses public operations/events. The complete example contains HTML, CSS, every button/input handler, subscriptions, stale-read protection and destruction cleanup. It creates only generated local points: no keys, hidden network requests or third-party credits are required. Copy it alongside the matching SDK dist directory and serve over HTTP.
Open complete example · Copy full HTML/CSS/JS · Canonical API index
| UI | Operation | Read state / event |
|---|---|---|
| Layer list / name | addLayer/removeLayer; sqs.setLayerMetadata | sqs.getLayers / getLayerMetadata; sqs.layerschange |
| Visibility / opacity / color | setLayoutProperty; setPaintProperty | getLayer; getPaintProperty/getLayoutProperty; sqs.layerschange |
| Ordering | moveLayer(id,beforeId?) | sqs.getLayers; sqs.layerschange |
| Zoom / north | zoomIn/zoomOut/resetNorth | sqs.cameraState/getMinZoom/getMaxZoom; move |
| Top-down / pitched view | setProjection({type:'mercator'});setPitch(0 or45) | sqs.viewModeState;move/terrain |
| Globe / flat projection | setProjection/getProjection | sqs.viewModeState;move/terrain |
| Local scale | sqs.scaleAt | move; projection/viewport changes |
| Credits | sqs.getAttributions | sqs.attributionschange |
| Cleanup | unsubscribe; remove referencing layers before sources; destroy host map | remove; no late UI refresh |
The table uses the common script facade. Standalone SDK methods are viewModeState/cameraState/scaleAt/getStyleLayers/getLayerMetadata/setLayerMetadata/getAttributions, without the script's sqs prefix; standard operations/events keep their canonical names. Reads require await. Layer names are application metadata, not inferred field semantics. getStyleLayers lists shared business layers, not internal basemap layers; read getStyle for the style document. Metadata replacement should preserve caller-owned keys.
The example edits constant circle paint values, and is not a universal expression or stylesheet editor. Applications choose other controls for expressions and tiled/internal style layers. The supported local scale is geographic/Mercator and connected pitched ground intersections, with globe support described in globe-scale; terrain-surface surveying is separate; the example reports that bound rather than inventing a scale. North reset preserves pitch; 2D sets explicit zero pitch;3D sets the documented 45 degree target, while globe and terrain are separate concepts.
Flush confirms the captured applied watermark and optionally an actual new frame; it does not imply all resources are loaded or animation is idle. Loading events and errors describe those conditions. Disable controls while an operation is pending. A monotonic refresh token rejects old async reads; changing the UI never mutates a snapshot directly. Script stop does not destroy the host map; the application's dispose action owns map destruction and unsubscription.
Layer API and bounds · Camera and projection · Scale calculation · Events and subscriptions
The sample passes duration:0 for zoom/north buttons; animations can instead use their documented options and completion events. Applied-frame confirmation does not certify animation completion.
Dimension and pitch switching: globe/terrain stay separate; buttons read canSwitchTo2d/3d.
Host conditions: fullscreen, system location and input
Application UI and its system host own these tools; the map core receives map operations. Common scripts currently expose neither fullscreen nor system-location permission requests and accept no DOM/native widget objects. GPU capability flags do not imply system permissions.
| Tool | Standalone web SDK host | Native/mobile host | Map operations/events |
|---|---|---|---|
| Fullscreen | After a user click, inspect document.fullscreenEnabled; call container.requestFullscreen, observe fullscreenchange and update the actual viewport; exit via document.exitFullscreen | Change host window/Activity state and call sqsm_map_set_viewport with actual dimensions; host determines availability | Refresh camera/scale and redraw; remove UI listeners on disposal |
| System location | In HTTPS secure context inspect navigator.geolocation; user-trigger getCurrentPosition and handle denial/timeout | Host owns permissions, service availability and coordinate conversion; mobile GIS/iOS integration remains separate | Pass WGS84lng,lat to jumpTo/easeTo and observe move/errors/completion; discard late callbacks after disposal |
| Touch | Inspect touchZoomRotate/touchPitch enabled/isActive; host may disable built-in input | Forward the unified input contract; Android standalone host is connected, device/mobile GIS/iOS acceptance remains separate | Shared camera events; see touch-navigation for scope |
| Keyboard | Focus map before using keyboard toggles; do not intercept text-field input | Window host forwards contracted keys; a mobile soft keyboard does not imply hardware-key support | Shared pan/zoom/bearing and move events; dispose input bindings |
A standalone web SDK UI click handler can obtain a host position and then use the map:
let disposed = false;
const locate = () => {
if (!globalThis.isSecureContext || !navigator.geolocation) return;
navigator.geolocation.getCurrentPosition(({coords}) => {
if (disposed) return;
view.easeTo({center:[coords.longitude,coords.latitude],zoom:14});
}, error => { if (!disposed) console.error(error.message); },
{enableHighAccuracy:false,timeout:10000,maximumAge:30000});
};
// Bind locate to caller-owned UI; set disposed=true before UI disposal.
This is browser host code. Portable scripts retain map operations and receive normalized coordinates from their host. Continuous watchPosition use must store the watch ID and clearWatch on stop. Hosts report unavailable permissions/services. Convert raw system coordinates to WGS84 before using map coordinates.
Use synchronous map.listens(type) for regular/once/delegated listeners owned by this facade; tables are independent. Seeevent listener queries.