Shared 3D lighting
Prefer map.setLight(light, options?) and await map.getLight(). The same script works in the browser, desktop debug panel and standalone native libraries built with scripting. SqsMap uses its own engine; similar MapLibre call syntax does not imply complete behavioral compatibility.
Portable script
import { map } from 'sqsmap';
const subscription = map.on('sqs.lightingchange', event => {
console.log(event.method, event.lightingState);
});
map.jumpTo({ center: [0, 0], zoom: 1 });
map.setProjection({ type: 'globe' });
map.setLight({ anchor: 'viewport', position: [1.15, 210, 30],
color: '#ffffff', intensity: 0.75 });
await map.sqs.flush();
console.log(await map.getLight());
console.log(await map.lighting.set({ view: 'globe', mode: 'sun',
sunTime: Date.parse('2024-06-21T12:00:00Z'), ambient: 0.25 }));
subscription.unsubscribe();
Confirm chainable setters with map.sqs.flush() and await queries. With a raw browser SDK MapView, use view.flush(); view.lighting.set() resolves to the applied state. Script event subscriptions belong to the run and are released when it ends. Use persistent sessions for continuing listeners.
Constants and coordinates
| Field | Default and meaning |
|---|---|
| anchor | viewport; alternatively map. viewport follows camera basis vectors; map uses east, north and zenith at the view center. |
| position | 1.15, 210, 30: positive radius, clockwise azimuth from north/view top, and polar angle down from zenith. Radius normalizes out without distance attenuation. Polar angle is 0–180°, azimuth normalizes to [0,360). |
| color | #ffffff; opaque CSS names, hex, rgb or hsl colors. Actual lit surfaces receive the tint; sRGB targets use a linear-space uniform. |
| intensity | 0.5; range 0–1, mapped to twice the legacy strength value. Existing per-view ambient settings remain in effect. |
Partial updates preserve omitted fields. The first common write starts from these defaults and configures both globe and building views. getLight returns null without a common light, including a solar/legacy override; it does not invent a MapLibre light for that configuration. Without an active 3D view it reads building configuration; flat map pixels do not receive surface lighting. Map-owned configuration survives style replacement and clearing until map destruction.
Solar and per-view extensions
map.lighting.state() returns {active,globe,building}. Each view contains mode, azimuth, elevation, strength, ambient, sunTime, utcOffsetMinutes and mapLight. map.lighting.set(options) resolves to the complete applied state. Specify globe/building as view; view is required without an active 3D view. The extension overrides only the selected view and clears its mapLight, preserving the other view.
mode is default/fixed/sun. Explicit azimuth accepts 0–360°, elevation -10–90°, strength 0–2 and ambient 0–1. A common position allows the lower hemisphere; inherited elevation can therefore reach -90° when switching modes. sunTime accepts now or Unix milliseconds within UTC years 1–9999, floored to seconds even for negative milliseconds. utcOffsetMinutes is an integer from -720 to 840 for time display and does not change the UTC instant. reset restores selected-view defaults before applying the remaining fields.
Events, errors and limits
sqs.lightingchange carries method, a deeply frozen historical lightingState, map identity and sequence. Later writes cannot change an earlier snapshot. Hosts validate the entire candidate and reserve output/notification budgets before committing it. Invalid fields, values, accessors or over-budget inputs leave configuration unchanged. Unsubscribe/off when finished; map destruction and script-session shutdown release remaining subscriptions.
Implemented values are constant opaque CSS names/hex/rgb/hsl colors, zero duration/delay property transitions, and omitted options or validate:true. Transparency, expressions, nonzero transitions and validate:false are not connected. lighting/lightColor are true; lightTransitions/lightExpressions are false. This does not establish browser/mobile support for every 3D layer. This stage verifies spherical pixels and native building/terrain surface tint paths and supplies no new 3D UI.
Native entry and complete example
C ABI reuses sqsm_map_scene_json: pass {"method":"setLight","args":[{"color":"#ffffff","intensity":0.75}]}; read with getLight or sqs.lighting.state and use sqs.lighting.set for per-view extensions. Release output with sqsm_map_bytes_free. Read events through the existing map queue or independent subscriptions. ABI1 and existing symbols remain unchanged. Native hosts still download HTTP resources and return responses.
The complete HTML/CSS/event-handler example is distributed beside its matching SDK and can be downloaded and deployed. Its default OpenFreeMap basemap displays engine-provided source credits; preserve required credits when selecting other providers.
Syntax references: Map API setLight and Light style specification. This page and the matching build manifest define the implemented scope.
Style reload still downloads resources asynchronously. flush({render:true}) is not a resource-readiness barrier. The complete example also reports basemapStatus; pixel acceptance waits for actual ready status and browser compositor frames.
Standard color names and modern numeric RGB/HSL syntax share the color input rules. cssNamedColors/cssModernRgbHsl capabilities are true. Native map.sqs.state().lightingState and persistent event.state.lightingState are deeply frozen snapshots.