Common layers implement all ten base types: circle, line, fill, fill-extrusion, raster, heatmap, background, symbol, hillshade and color-relief. Sections below specify actual properties, projections and combinations; unsupported scope rejects explicitly. Callers own layer/tool UI through APIs and events. Common layers currently support circle/line/fill/raster,planar heatmap,source-less background and point image symbols. The type sections below specify actual properties/projection limits. Unsupported combinations reject explicitly. Callers own layer/tool UI and drive it through the shared API/events.
Shared GeoJSON style layers (07.2 / 08.1)
map.addLayer(spec, beforeId?) attaches a registered source using circle, line, or fill. Several layers may reuse one source. Source registration creates no implicit layer; adding a layer preserves the camera. Omitted beforeId appends to the shared layer group above legacy GIS vector layers. moveLayer orders this group only; legacy numeric layer calls retain their existing meaning.
import { map } from 'sqsmap';
map.addSource('trees', { type: 'geojson', data: {
type: 'FeatureCollection', features: [{ type: 'Feature', id: 'oak',
properties: { height: 12, enabled: true },
geometry: { type: 'Point', coordinates: [116.4, 39.9] } }]
}});
map.addLayer({ id: 'halo', type: 'circle', source: 'trees',
paint: { 'circle-color': '#ffffff', 'circle-radius': 12 } });
map.addLayer({ id: 'trees', type: 'circle', source: 'trees',
paint: { 'circle-color': '#008800', 'circle-radius': ['coalesce', ['get', 'height'], 6] },
filter: ['==', ['get', 'enabled'], true], metadata: { name: 'Trees' } });
await map.sqs.flush();
const trees = await map.getSource('trees');
await trees.updateData({ update: [{ id: 'oak', addOrUpdateProperties: [{ key: 'height', value: 15 }] }] });
map.setLayoutProperty('trees', 'visibility', 'none');
map.setPaintProperty('halo', 'circle-color', '#ff0000');
map.moveLayer('halo', 'trees');
await map.sqs.flush();
const description = await map.getLayer('trees');
const layers = await map.sqs.getLayers();
// Remove referencing layers before their source.
map.removeLayer('trees').removeLayer('halo').removeSource('trees');
await map.sqs.flush();
Queries require await. Writes are chainable; flush confirms application. getLayer returns a description copy and preserves raw metadata; editing that copy does not edit the map. A null paint/layout value restores the default. setFilter(id, null) clears the filter. Zoom ranges include the lower bound and exclude the upper bound, defaulting to 0–24. Layout visibility differs from effective visible; range changes do not rewrite layout. getLayers returns order, non-reused layerInstanceId, bound source identity, data/cache revisions, effective visibility, display feature count and dynamic-style warningCount. GIS layers, internal basemap layers and raster overlays are separate. getStyle is connected for the documented style subset; read the style guide for asynchronous loading/diff and unsupported options.
Use the SqsMap extensions map.sqs.setLayerMetadata(id, metadata) / getLayerMetadata(id) for panel labels and user information. Matching SDK methods are setLayerMetadata / getLayerMetadata. The object replaces all metadata; null clears it. Without name, the label is the layer ID. name must be a nonblank string without NUL and at most 4096 UTF-8 bytes; other keys remain raw. Metadata writes emit sqs.layerschange and preserve layer/source identities and order. A metadata-only edit does not rebuild the display cache at the same zoom.
map.sqs.setLayerMetadata('trees', { name: 'Trees', category: 'survey' });
await map.sqs.flush();
const metadata = await map.sqs.getLayerMetadata('trees');
Like property setters, setFilter accepts an optional { validate: true } third argument. false reports CAPABILITY_UNAVAILABLE; unknown keys and wrong types report INVALID_ARGUMENT.
circle selects points, fill polygons, and line includes lines and polygon outlines. Collection children inherit their parent's identity and typed properties. Display filters do not edit source data. Source replacement validates every dependent display cache before committing; normal argument, budget or version failures preserve the previous source, description, identities and frame. Referenced sources cannot be removed. Removing a shared layer through the legacy numeric delete entry also releases its logical source reference.
Canonical planar zoom drives filters, paint and visibility ranges. Browser radius/width use CSS pixels. Zoom paint retains the shared expression restriction to a top-level step/interpolate. Spherical circle/line/fill are supported; pitched common layers are connected; other CRSs and the remaining type/layout subsets retain explicit limits. Editable tiled source-layer and symbol behavior are documented in the tiled-vector and style guides; shared line-gradient uses lineMetrics. CSS color input support is documented in the color guide. validate:false cannot bypass checks. Invalid dynamic values use style fallback or skip filtered features and contribute to warningCount rather than reporting a source loading failure.
Limits: 128 shared layers and 128 total shared/legacy render layers; 64 KiB, 4096 nodes and depth 32 per description. A conservative estimate limits all display caches to 128 MiB, including collection attribute expansion and each layer's source copy. Large shared sources may therefore reject earlier. This does not bound the entire host's peak memory.
Successful logical layer writes emit sqs.layerschange with method, id and layerCount. Failed writes do not notify. Use the common on/off/once contract; flush does not consume callbacks, so await once before unsubscribing. Source-data refresh preserves layer instances/order and emits sourceschange, not fabricated layer additions. Use map.on('sqs.layerschange',callback) as the canonical observer; prior SDK aliases remain compatible. Old npm builds explicitly reject missing support. Linux hardware rendering and actual QuickJS are verified; Windows/macOS, mobile and real browser GPU runs remain separately recorded.
Shared spherical line/fill and complete HTML: spherical surfaces.
Standalone SDK on/off/once also accepts sqs.layerschange and sqs.sourceschange; aliases share subscriptions. See event names for host differences and cleanup.
For complete caller-owned UI, state/event mapping, all handlers and cleanup, see layer panels and tools. Current pitched/globe, CSS colors, media raster and tiled styles have separate documented subsets; early phase labels above do not replace their current guides.
Shared raster tile layers now reference raster sources, preserve logical layer order and share decoded pixels. See raster tiles for scope and budgets.
Shared MVT layers and queries
Vector sources now display standard circle,line,fill layers through addSource/addLayer. Each layer requires source-layer. Layers share downloads and cached content, with common geometry for planar,pitched and globe views. Planar rendering interleaves fills,lines and points in logical layer order: moveLayer can place a fill above a circle while retaining spatial-cell culling and LOD.
import {map} from 'sqsmap';
map.addSource('roads',{type:'vector',tiles:['https://your-server.example/{z}/{x}/{y}.pbf'],attribution:'Your provider'});
map.addLayer({id:'roads-line',type:'line',source:'roads','source-layer':'transportation',paint:{'line-color':'#e87925','line-width':3}});
await map.sqs.flush({render:true});
console.log(await map.querySourceFeatures('roads',{sourceLayer:'transportation'}));
Scheduling/cancellation reuse shared tile handling, including TileJSON,setTiles/setUrl,XYZ/TMS,world copies and attribution. Each MVT response permits8MiB,32 source layers,50,000 features and500,000 vertices. A map permits64 visible tiles,32 pending requests and64MiB decoded tile cache; visible source data additionally obeys16MiB JSON,50,000 features,500,000 coordinates and resident source budgets. Over-budget responses fail explicitly and failed refresh retains old content. Parent/child fallback is not connected; cached invisible tiles are excluded from queries.
querySourceFeatures requires sourceLayer. queryRenderedFeatures filters by display layer and returns sourceLayer,original MVT id and attributes, with WGS84 coordinates including visible world copies. Native/shared script reads use await. querySourceFeatures retains tile fragments; queryRenderedFeatures deduplicates stable IDs per display layer/sourceLayer, while features without IDs retain fragments. GeoJSON/media sources cannot specify source-layer. metadataLoaded describes metadata; tileState and loaded describe actual current-view readiness.
vectorTileSourceStore=true represents this MVT subset, not complete vector style compatibility. MVT promoteId,volatile,feature state and stable-ID rendered-query deduplication are connected. Other MVT types including symbols/extrusions,buffer clipping/geometry merging,MLT and MVT parent/child fallback remain pending. Android standalone-host acceptance is separate from mobile application/device acceptance. Existing setStyle(URL) basemaps retain their separately documented scope.
The complete HTML includes every button,query,credit and disposal action. The portable acceptance script uses locally generated MVT through real native QuickJS and WASM main-thread/strict Worker. Replace the template and display required provider credits for real services.
Shared MVT feature state is connected per sourceLayer/id; see feature state.
Shared type expressions (08.5)
Supports MapLibre-style boolean/number/string/object assertions with ordered candidates, array item-type/length assertions, typeof,properties and get/has with optional objects and string-name expressions. Syntax follows the official expression reference; the shared Rust evaluator is independently implemented without the MapLibre runtime.
map.setPaintProperty('places-layer','circle-color',
['case',['boolean',['feature-state','selected'],false],'#ff00ff','#0000ff']);
map.setPaintProperty('places-layer','circle-radius',
['number',['get','height',['object',['literal',{height:18}]]],6]);
await map.sqs.flush({render:true});
Assertions do not coerce numeric strings. They select the first candidate of the requested type and short-circuit later evaluation; failure uses existing paint defaults/warnings or explicit query-filter errors. array supports value,type/value,type/length/value forms with string/number/boolean item types and nonnegative integer lengths up to65536. Array typeof results include item type/length, e.g.array<number, 2>; mixed items use value. get returns null for missing keys,has distinguishes missing from present null,and invalid object inputs fail explicitly.
This describes JSON types; collator, the full format/image value system and remaining expressions stay in subsequent tasks; text-field supports format text sections with font-scale/text-color, complete PBF text-font stacks, top/center/bottom vertical-align, registered RGBA image sections and case/coalesce/match/let/var combinations, described in formatted text, font stacks, section alignment and RGBA image sections. Images use pixelRatio dimensions and retain RGBA color multiplied by text-opacity; missing images are actual null, SDF sections reject and a top-level text-field image must be wrapped in format. Existing node/depth,source and display budgets apply; feature-state is paint-only. GeoJSON/shared MVT use identical semantics; setStyle(URL) basemaps retain their separate expression scope. The complete HTML and portable script include selection,ordering,views,queries,credits and disposal.
Variable scope (08.6)
Shared paint,filter and query expressions support let/var. Variables are visible in the let result; inner bindings shadow outer ones. Binding values resolve only enclosing-scope variables. Bindings evaluate on demand,so unused runtime errors do not execute. Names use nonempty ASCII letters/digits/underscores,up to256 bytes. Unbound names and invalid structures reject before mutation.
map.setPaintProperty('places-layer','circle-color',
['let','selected',['boolean',['feature-state','selected'],false],
['case',['var','selected'],'#ff00ff','#0000ff']]);
map.setPaintProperty('places-layer','circle-radius',
['let','large',18,['step',['zoom'],6,4,['var','large']]]);
await map.sqs.flush({render:true});
Camera zoom may drive a terminal step/interpolate inside outer let expressions; it cannot appear in binding values or other positions. Shared layers continue reevaluating actual zoom. Each evaluation permits8192 steps/64 levels; AST limits remain1024 nodes/32 levels. Budget failures use existing paint defaults/warnings; layer/query filters report RESOURCE_LIMIT and mutations leave no partial layer/reference.
The complete HTML and portable script include all buttons,credits and cleanup through native and real WASM main-thread/strict Worker. Implementation is independent against the public expression specification,without MapLibre code. Remaining operators and complete layer types continue in tasks.
Shared planar heatmap layers
Standard addLayer(type:heatmap) now references GeoJSON points or MVT point source layers; MVT requires source-layer. Rendering reuses the independently implemented GPU heat module and shared ordering,filters,visibility,zoom,credits and state weights. Applications provide their own tool UI.
import {map} from 'sqsmap';
map.addSource('points',{type:'geojson',data:{type:'Feature',id:1,properties:{weight:1},geometry:{type:'Point',coordinates:[0,0]}}});
map.addLayer({id:'heat',type:'heatmap',source:'points',paint:{
'heatmap-weight':['number',['get','weight'],1],
'heatmap-radius':36,'heatmap-intensity':1,'heatmap-opacity':0.8,
'heatmap-color':['interpolate',['linear'],['heatmap-density'],0,'#00000000',1,'#ff0000ff']
}});
await map.sqs.flush({render:true});
console.log(await map.queryRenderedFeatures(await map.project([0,0]),{layers:['heat']}));
Radius is positive and at most256 CSS pixels,intensity0..1000,opacity0..1. The color ramp uses linear heatmap-density with strictly increasing0..1 stops,at most32 constant colors. Weights accept attributes/state/variables,finite nonnegative values,and no zoom; rendered weight×intensity clamps to128. Radius/intensity/opacity accept constants and existing zoom interpolation. Owned display caches permit16384 heat points per map,including hidden layers.
Rendered queries use nonzero weight/intensity/opacity and kernel radius. Color descriptions retain the ramp rather than inventing per-point density colors; state snapshots remain source/source-layer scoped. Invalid weights are omitted and counted as warnings. Invalid/over-budget writes leave no partial layer/source reference.
Currently planar,including planar overlays on URL basemaps. Pitch,globe and combinations with shared raster layers reject explicitly and continue in3D tasks. This is a documented subset,with exponential ramps,additional parameter combinations and the mobile host still pending. Capabilities commonHeatmapLayers/heatmapPlanar are true.
The complete HTML includes weight,opacity,radius,visibility,order,query and disposal handlers. The portable script uses identical logic in native/main-thread/strict Worker. Example points are locally generated; provide required credits for real data.
Source-less background layers
Standard addLayer supports type:background without source. It creates no fake source,count,reference or credit. Supports background-color/background-opacity and shared visibility,order,zoom ranges,name/metadata. Other layer types still require real sources.
import {map} from 'sqsmap';
map.addLayer({id:'background',type:'background',paint:{
'background-color':'#00ff00','background-opacity':0.8
}});
await map.sqs.flush({render:true});
console.log(await map.getLayer('background')); // No source member
console.log(await map.sqs.getLayers()); // This layer has source:null
map.moveLayer('background'); // Move above earlier layers
await map.sqs.flush({render:true});
A bounded fullscreen GPU pass follows logical layer order and applies opacity once. Backgrounds return no fabricated query features. source/source-layer/filter,feature attributes and feature-state reject before mutation without leaving a source. Constants/shared zoom expressions retain existing color/opacity rules.
LayerInfo.source may now be null; getLayer/getStyle omit background source. Caller-owned panels should handle layer.source?.id. Existing sourced layers keep their identities/references; cleanup never removes an empty source. Currently planar; pitch/globe/shared-raster combinations reject explicitly and continue in3D tasks.
The complete HTML includes color,opacity,visibility,ordering,query and disposal handlers. The portable script verifies identical native and real WASM main-thread/strict Worker behavior. Example data are locally generated.
Point image symbols
Standard symbol layers now support planar Point/MultiPoint and MVT points. Register RGBA8 images with addImage or use an already loaded sprite. icon-image accepts a name, attribute expression or typed image/case/match/coalesce/let-var expression; icon-size is0..16 and icon-rotate is-360..360 degrees, each accepting a number or attribute/lexical/global-state expression,and icon-anchor supports nine standard anchors. icon-opacity uses common paint expressions,state and zoom. Visibility,ordering,filters and zoom ranges use the shared layer API. setLayoutProperty edits these layouts. Updating/removing images refreshes rendering and queries without replacing layer identity.
import {map} from 'sqsmap';
map.addImage('marker',{width:40,height:20,
data:Array.from({length:800},()=>[255,0,0,255]).flat()},{pixelRatio:2});
map.addSource('points',{type:'geojson',data:{type:'Feature',id:1,
properties:{icon:'marker'},geometry:{type:'Point',coordinates:[0,0]}}});
map.addLayer({id:'icons',type:'symbol',source:'points',layout:{
'icon-image':['get','icon'],'icon-allow-overlap':true,'icon-ignore-placement':true
},paint:{'icon-opacity':1}});
await map.sqs.flush({render:true});
map.setLayoutProperty('icons','icon-rotate',90);
await map.sqs.flush({render:true});
Common point collision is implemented with both options defaulting to false;explicit true controls overlap and occupied space as described below. Plain/formatted text-field is available; line placement and other undeclared layouts remain pending;SDF/recoloring and demand events are implemented below. Layout rejects feature-state; use state in paint. Missing images,zero size or zero opacity have no rendered hits. Queries use actual dimensions,pixelRatio,rotation and anchor footprints;transparent image areas currently use rectangular footprints. Each map owns at most16384 image points including hidden layers;the atlas retains the2048-edge and existing image budgets.
Planar rendering is supported;pitch,globe and common raster combinations reject explicitly. This is a symbol subset,not full symbol compatibility. commonPointIconSymbols is true;the mobile host is pending. The complete HTML includes update,rotation,anchor,opacity,visibility,image removal/restoration,order,query and disposal handlers. The portable script uses the common map API. Example points/images are generated locally;retain source attribution for real data and basemaps.
Shared symbol demand events and SDF recoloring
Planar common symbols now emit styleimagemissing for visible points/layers with nonzero size/opacity. Names are deduplicated;events carry id and styleGeneration. Filling then deleting an image,leaving then reentering demand,or replacing the style generation rearms notifications. Style and common-layer demand share one bounded set of at most128 missing names;output/event-budget failure does not acknowledge demand early. Listeners may addImage to complete it. Unsubscribe,stop and destruction release listeners.
import {map} from 'sqsmap';
export const sessionMode='persistent';
const subscription=map.on('styleimagemissing',async event=>{
if(event.id!=='marker')return;
map.addImage(event.id,{width:16,height:16,
data:Array.from({length:256},()=>[0,0,0,255]).flat()},{sdf:true});
await map.sqs.flush();
});
map.addSource('points',{type:'geojson',data:{type:'Feature',
properties:{},geometry:{type:'Point',coordinates:[0,0]}}});
map.addLayer({id:'icons',type:'symbol',source:'points',layout:{
'icon-image':'marker','icon-allow-overlap':true,'icon-ignore-placement':true
},paint:{'icon-color':'#ff0000','icon-opacity':0.8}});
await map.sqs.flush({render:true});
// Release with subscription.unsubscribe();stopping the script also releases it.
SDF images use the alpha distance field,a0.5 boundary and screen-derivative smoothing. icon-color supports common paint expressions,attributes/state/zoom and recolors sdf:true images only. Ordinary RGBA images retain their colors. Color alpha and icon-opacity combine once;zero final alpha produces no query hit. updateImage retains SDF,pixelRatio and identities;distance-image pixel updates refresh rendering. Transparent image areas still query by rectangular footprint,not a per-pixel mask.
Native retained scripts,WASM main-thread/strict Worker and the desktop host share these rules;the mobile host is pending. commonPointIconSDF/commonPointIconMissingImages are true. Shared text and point collision are available; line placement,globe/pitch and common raster combinations remain pending. The complete HTML includes every image/color/demand handler and11 controls. The portable retained script demonstrates callback completion. Example images/points are generated locally.
Shared point symbol collision and ordering
Planar symbols now support default collision placement. icon-allow-overlap and icon-ignore-placement accept boolean constants or expressions, defaulting to false. icon-padding accepts constants or numeric expressions in0..128 CSS pixels,default2. The first controls checking occupied space;the second controls blocking later symbols. MultiPoint positions are placed individually,and queries inspect placed points only. Hidden,missing-image,zero-alpha and offscreen symbols occupy no space. Omitting icon-image leaves an empty layout;setting it to null restores that empty layout.
symbol-sort-key accepts finite numbers or numeric attribute/zoom expressions. Ascending keys determine placement/drawing priority. symbol-z-order accepts auto/source/viewport-y,default auto. Without a sort key,auto/viewport-y draw by screenY when overlap is true or ignore-placement is false;source retains input drawing order. Upper common layers get placement priority. Queries follow actual icon drawing order. These parameter semantics follow the MapLibre symbol specification;the implementation reuses this engine's existing collision grid.
import {map} from 'sqsmap';
map.addLayer({id:'icons',type:'symbol',source:'points',layout:{
'icon-image':['get','icon'],'symbol-sort-key':['get','rank'],
'icon-padding':2
}});
await map.sqs.flush({render:true});
map.setLayoutProperty('icons','icon-allow-overlap',true);
map.setLayoutProperty('icons','symbol-z-order','viewport-y');
await map.sqs.flush({render:true});
Register the actual icon/rank fields and images first,or complete missing images in a listener. Invalid numeric sorting values reject;layout still rejects feature-state while paint supports it. Camera,viewport and actual style-density changes trigger placement without replacing source/layer identities. Contiguous identical icon draws batch GPU submission;MultiPoint splitting does not copy the entire point-index list. Each map owns at most16384 image points;the32-pixel grid uses at most64 buckets per box and1M comparisons. Failed candidates do not apply partial placement.
This stage covers common planar point-image layers. URL basemap labels use a separate layout domain;cross-domain collision remains pending. commonPointIconCollisions is true;commonAndURLSymbolCollisions is false. Point text is documented below;line placement,other parameters,3D/raster composition and mobile hosts remain pending. The complete HTML contains every handler for12 controls. The portable script covers placement,ordering,queries,zoom and layout reset. Example points/images are generated locally.
Shared point text labels
Standard planar symbol layers now draw Latin/Chinese text on Point/MultiPoint/MVT points. text-field accepts a string or common string expression. text-size accepts0..256 CSS pixels or a common numeric expression,default16. text-anchor supports nine anchors,default center;text-offset uses two em values and text-rotate accepts-360..360 degrees or a common numeric expression. text-color/text-opacity support common attribute,state and zoom paint expressions. Text overlap/ignore options default false and padding defaults2. Whole labels participate in common collision/order;queries inspect placed label rectangles. Image/text combinations currently require separate layers.
import {map} from 'sqsmap';
map.addSource('points',{type:'geojson',data:{type:'Feature',id:1,
properties:{name:'Sqs地图'},geometry:{type:'Point',coordinates:[0,0]}}});
map.addLayer({id:'labels',type:'symbol',source:'points',layout:{
'text-field':['get','name'],'text-size':18,'text-anchor':'center'
},paint:{'text-color':'#ff0000','text-opacity':1}});
await map.sqs.flush({render:true});
map.setLayoutProperty('labels','text-offset',[1,0]);
map.setPaintProperty('labels','text-color','#00ff00');
await map.sqs.flush({render:true});
Existing glyph shaping and bundled HarmonyOS Sans SC provide the same actual font on native/WASM (24px glyphs,SDF boundary near192/255). text-font retains1..8 ordered family names,but this shared text stage uses the documented bundled fallback;requested names are not advertised as loaded external fonts. New external glyph demand,complex shaping,additional text properties,line/combined image-text placement and3D/raster composition remain pending. Unsupported bundled glyphs reject explicitly and preserve the previous layer. Control language is independent from data text/font.
A separate R8 atlas preserves the user image atlas and registration budget. Glyphs add no listImages entries or fake sources. Limits are256 characters/4096bytes per label,16K common symbol points,65536 glyph quads,and8192 distinct glyphs subject also to the2048 atlas capacity. Hidden caches count. Glyph caches are reused;size,rotation,anchor/offset,source/state and real viewport/density changes refresh shared placement. Color alpha and opacity combine once;zero final alpha has no hit. The initial08.12 fixed typography is superseded by the08.13 properties below;full MapLibre shaping compatibility is not claimed.
commonPointTextLabels is true;commonTextExternalGlyphDemand is false. Native,WASM main-thread/strict Worker and desktop binding are connected;the mobile host,new desktop text GUI and external platforms remain pending. The complete HTML includes every text control handler. The portable script uses the same API. Points are generated locally;the distribution includes the font license in its third-party notices.
Configurable text typography (08.13)
text-max-width defaults to10em,range0..256;0 disables automatic wrapping while explicit newlines remain. text-line-height defaults to1.2em,range0..256;text-letter-spacing defaults to0em,range-16..256. text-justify accepts center(default),left,right,auto;auto follows the horizontal position of the evaluated text-anchor. text-transform accepts none(default),uppercase,lowercase. Unicode case conversion precedes length and glyph budgeting.
text-size,text-rotate and the three numeric typography properties support common numeric expressions using attributes or zoom. Each evaluated result must be finite and within range. text-padding accepts0..128 constants or numeric expressions. Updates refresh glyph geometry,whole-label collision and queries. Wrapping uses actual glyph advances with whitespace word boundaries and character fallback for oversized/CJK tokens. Complex shaping, bidirectional text, complete Unicode line breaking, remaining rich text types and font files remain pending; text-only format sections support different sizes and colors; external PBF glyph services are connected.
map.setLayoutProperty('labels','text-max-width',10);
map.setLayoutProperty('labels','text-line-height',1.5);
map.setLayoutProperty('labels','text-letter-spacing',0.1);
map.setLayoutProperty('labels','text-justify','center');
map.setLayoutProperty('labels','text-transform','uppercase');
map.setLayoutProperty('labels','text-size',['interpolate',['linear'],['zoom'],0,12,10,24]);
await map.sqs.flush({render:true});
Property names,units and defaults reference theMapLibre style specification. Execution and typography use SqsMap's shared core. Legacy label entry points retain their behavior. Thecomplete HTML exampleincludes every button handler. Standalone SDK code uses map.flush;script code uses map.sqs.flush.
Shared fill-extrusion buildings (08.14)
GeoJSON/MVT Polygon/MultiPolygon support fill-extrusion. Height/base are metres above the flat ground plane,default0,range0..100000;base must not exceed height. Color defaults black,opacity1,vertical-gradienttrue. Common attribute/state/zoom expressions provide numeric,color and boolean values. Metres are converted to display height at the polygon's latitude.
map.addLayer({id:'buildings',type:'fill-extrusion',source:'your-polygons',paint:{
'fill-extrusion-height':['get','height'],
'fill-extrusion-base':0,
'fill-extrusion-color':'#ef4444',
'fill-extrusion-opacity':1,
'fill-extrusion-vertical-gradient':true
}});
map.setPitch(45);
await map.sqs.flush({render:true});
Common layer/source identity,filter/order,zoom,state and property updates are retained. Flat views show the roof footprint/courtyard holes. Perspective views use actual roofs,outer/courtyard walls and existing 3D lighting. The gradient multiplies bottom wall RGB by0.75 and preserves top color. Alpha/opacity combine once. Picking uses the same mesh,clips near/far depth and tests roof/wall projection. Hidden/transparent layers do not hit;depth occlusion between other layers is not additionally promised.
Each geometry is limited to500K vertices/1.5M indices,visible rendering retains the scene index budget,and queries inspect at most500K triangles. Mercator latitude is limited to±85.051129. Invalid height pairs/candidate budgets reject before updates. Globe,real terrain,draped buildings,patterns/translate and other standard properties remain pending;unsupported properties reject explicitly. MVT buffer clipping/fragment deduplication remain source tasks. Consumers provide UI. Thecomplete HTMLcontains all button handlers.
Elevation tiles and hillshade (07.12 / 08.15a)
Common raster-dem sources now decode lossless PNGs using mapbox (default), terrarium or custom. Heights in meters are -10000 + (R65536+G256+B)0.1 for mapbox, and R256+G+B/256-32768 for terrarium. Custom uses RredFactor+GgreenFactor+B*blueFactor+baseShift; channel factors default to 1 and baseShift to 0. Custom fields are rejected for other encodings. Factors and decoded heights have an absolute limit of 1e8. Transparent pixels are nodata, not zero-height terrain. JPEG is rejected.
map.addSource('dem',{
type:'raster-dem',tiles:['https://your-provider/{z}/{x}/{y}.png'],
tileSize:512,encoding:'terrarium',attribution:'Data provider credit'
});
map.addLayer({id:'shade',type:'hillshade',source:'dem',paint:{
'hillshade-method':'basic',
'hillshade-illumination-anchor':'map',
'hillshade-illumination-direction':335,
'hillshade-illumination-altitude':45,
'hillshade-exaggeration':0.5
}});
await map.sqs.flush({render:true});
08.15c adds standard/viewport defaults and five single-light algorithms. Omitted paint now runs; multiple-light arrays still reject. Supported inputs: one direction 0..359 degrees, altitude 0..90, intensity 0..1 and shadow/highlight/accent colors. Numbers/colors use common zoom expressions; feature properties, state and filters are unavailable. Zero degrees means north; 90 means east. Our implementation mixes shadow/highlight using metric slopes and cosine illumination, then applies an accent with 25% slope weight. Intensity controls final alpha. Pixel equivalence with other engines is not promised.
Native and WASM share decoding and cached derived pixels, public layer ordering, visibility, zoom range and revisions. Paint changes update the GPU texture revision. PNG responses are limited to 4 MiB and decoded sides to 1024 pixels. Original RGBA plus f32 heights count toward the map-wide 64 MiB tile cache; derived RGBA counts toward the 128 MiB layer budget. Registration alone downloads nothing; use actual source events/tileState for readiness.
TileJSON, setTiles/setUrl, bounds, zoom limits, credits and common volatile policy are supported. getSource returns a raster-dem handle; source.sqs.getTileMetadata().encoding identifies the decoder. Source tileState includes height memory. Pixel layers have no queryable vector features or feature-state. Supply a real provider URL and display its required credits.
Tile borders currently use one-sided differences. Neighbor stitching, multiple-light arrays, globe and mobile device acceptance remain pending. Hillshade colors the DEM; setTerrain separately enables real meshes/elevation queries and allows this coloring to drape.
Names follow the MapLibre source specification and hillshade specification. SqsMap implements its own shared decoder and rendering.
Elevation coloring and common CSS colors (08.15b)
color-relief uses a common raster-dem source. color-relief-color accepts a constant CSS color, a linear interpolate ramp or a step ramp with "elevation" in meters. Up to 32 strictly increasing numeric stops are supported, each with an absolute limit of 1e8 and a constant color. Default is black. Linear interpolates RGBA and clamps outside its range; step adopts the new color at a threshold. Negative heights are supported; transparent nodata stays transparent. The input is scoped to the elevation ramp and does not become a feature field.
map.addLayer({id:'relief',type:'color-relief',source:'dem',paint:{
'color-relief-color':['interpolate',['linear'],['elevation'],
-100,'#2563eb',0,'lime',2000,'rgb(160 100 40)',5000,'white'],
'color-relief-opacity':0.8
}});
map.setPaintProperty('relief','color-relief-color',[
'step',['elevation'],'blue',0,'lime',2000,'brown',5000,'white'
]);
await map.sqs.flush({render:true});
Opacity defaults to 1, ranges from 0 to 1, and accepts common zoom expressions. Final alpha multiplies color alpha by opacity once. Layers reuse decoded DEMs; palette/opacity, ordering, zoom and visibility updates change derived texture revisions without editing elevations. Vector features, feature-state and filters are unavailable. Globe, other interpolation modes, dynamic stop colors and further elevation-specific expressions remain pending. Budgets match raster-dem/hillshade.
Common circle/line/fill/fill-extrusion, symbol, background, heatmap and elevation colors now reuse the existing CSS parser: hex, 148 named colors, RGB/RGBA and HSL/HSLA, case variations, percentages, whitespace/slash syntax and angle units. Interpolation uses sRGB bytes. Invalid/nonfinite inputs reject; other color spaces are not promised.
The complete HTML/CSS/button example uses SqsMap-generated demonstration heights, not real terrain. Replace the source and display provider-required credits. Naming follows the MapLibre color-relief specification; SqsMap implements its own rendering.
Default hillshade and light anchors (08.15c)
A hillshade layer runs without paint. Defaults are standard/viewport, direction 335 degrees, altitude 45 degrees and exaggeration 0.5. Supported single-light configurations are standard, basic, combined, igor and multidirectional. Existing direction/altitude ranges, colors, intensity and zoom expressions remain available. Multiple-light arrays are pending and reject explicitly.
map.addLayer({id:'shade',type:'hillshade',source:'dem'});
map.setBearing(90);
map.setPaintProperty('shade','hillshade-illumination-anchor','map');
map.setPaintProperty('shade','hillshade-method','combined');
await map.sqs.flush({render:true});
// null restores standard/viewport defaults.
map.setPaintProperty('shade','hillshade-method',null);
map.setPaintProperty('shade','hillshade-illumination-anchor',null);
Map lighting follows north. Viewport lighting follows the top of the viewport; current bearing is added to the actual illumination direction. Only derived layer textures refresh. Source data revisions, resource requests, credits and source events do not change due to the lighting view parameter. Native Session, browser renderChecked and desktop common-layer refresh apply the same rule before drawing. Layer instances, ordering and original DEMs remain stable.
SqsMap implements its own algorithms: standard mixes direction/altitude lighting and slope coverage; basic uses cosine illumination; combined applies a further slope factor; igor uses reduced coverage; a single-light multidirectional configuration uses cosine illumination. Accent uses a 25% slope weight, and intensity multiplies final alpha. Input shapes follow the reference specification; pixel equivalence with other engines is not promised.
Neighbor stitching, multiple-light arrays, globe and device acceptance remain separate tasks. Budgets are shared with elevation sources/coloring.
Common terrain surfaces and elevation queries
setTerrain/getTerrain/queryTerrainElevation use common raster-dem sources, our decoder and the existing real shared-depth/lighting/picking renderer. No display layer is required. Select Mercator first. Registration downloads nothing; terrain binding schedules visible tiles. Exaggeration defaults to 1 and ranges from 0 to 20. Null disables terrain and releases its reference.
import {map} from 'sqsmap';
map.setProjection({type:'mercator'});
map.addSource('dem',{type:'raster-dem',tiles:['https://your-provider/{z}/{x}/{y}.png'],
encoding:'terrarium',attribution:'Provider credit'});
await map.setTerrain({source:'dem',exaggeration:1.5});
map.setPitch(45);
await map.sqs.flush({render:true});
const config=await map.getTerrain();
const height=await map.queryTerrainElevation([116.4,39.9]);
map.on('terrain',event=>{console.log(event.terrain);});
Common queries return number/null: bilinear decoded meters multiplied by current exaggeration. Disabled, unloaded, nodata or unavailable tiles return null, never implicit zero. Queries read the highest cached level and fetch nothing. Bound source instances remain stable; removing a referenced source conflicts, and disabling releases it. getTerrain is normalized configuration; getSourceInfo supplies actual readiness/errors/revisions. Terrain events contain historical configuration in terrain, or null. Credits participate in getAttributions; callers display them.
Enabling preserves logical camera settings and does not automatically change pitch. Display LOD grids contain up to 33x33 vertices per tile with latitude-scaled meter heights, real triangle normals and matching surface indices. Bilinear data query precision differs from mesh LOD. Conservative CPU mesh/raster/pick accounting is limited to 32 MiB; displayed z has an absolute limit of 1e9 Mercator meters. Shared PNG/elevation cache budgets apply. Style objects support the terrain root; full replacement updates/disables terrain and cancels old tile work.
Current scope is Mercator plus existing GeoJSON circle/line/fill 3D paths. Common tile rasters and hillshade/color-relief now drape in layer order. Registered image/video/canvas convex quads also drape; independent URL raster styles, fill-extrusion and symbol/heatmap/background combinations retain explicit limits. Disable terrain before globe. Neighbor stitching/skirts, adaptive LOD, overlay draping/elevated focus/terrain gesture anchors and overlay queries, and native/mobile device acceptance remain separate work; complete MapLibre terrain compatibility is not claimed.
The desktop map.sources.add local DEM path remains available. Its getTerrain may return TerrainState; queryTerrainElevation returns a TerrainElevation object with raw height, datum and nodata reason, without display exaggeration. Use common map.addSource for consistent cross-platform number/null results. Local file extensions remain capability-dependent. Standalone C ABI reuses source JSON commands setTerrain/getTerrain/queryTerrainElevation, adding no ABI symbols.
Names follow MapLibre setTerrain and elevation query. SqsMap implements its own meshes and rendering.
Terrain project/unproject now use actual display triangles and explicitly reject missing surfaces; see terrain coordinates. Common tile rasters and DEM coloring drape in layer order without double opacity; the complete imagery example includes every control and credit. Browser reset disables terrain, removes common layers/sources and resets pitch before geographic projection. Ordinary paint adds cubic Bézier interpolation and scalar math; remaining special values/properties stay separate work.
Additional ordinary style expressions
rgb/rgba/to-rgba provide property colours and channel arrays; at/length/in/index-of/slice/split/join/upcase/downcase provide bounded array and Unicode string operations. interpolate accepts equal-length numeric/colour arrays; interpolate-lab/hcl provide CIE Lab D50/HCL colours and colour arrays. HCL uses the shorter hue path, separate alpha interpolation and byte RGB clipping. String indices count code points, scans consume the 8192-step budget, and join/case output is capped at4096 bytes. Colours remain CSS strings, with no distinct Color value. Dedicated heatmap-density/elevation ramps retain their own scope. See the website colour, lookup and colour-space guides for limits.
is-supported-script checks the current simple shaping capability; complex scripts conservatively return false and font coverage is not guaranteed. See writing-system legibility.
Shared MVT point/line geometry clipping is connected in07.14a; raw source queries stay separate from rendered queries. Polygon/pixel clipping and merging remain pending. See buffer geometry.
Shared MVT polygon/hole clipping and explicit transparent fill outlines are connected in07.14b. Raw source queries remain intact; stroke pixel boundaries and merging remain pending. See polygon clipping.
08.36: text-anchor, text-justify and text-transform accept string expressions evaluated per feature from attributes/global state. Drawing, collision and queries share the refreshed layout. Invalid result types/enumerations reject the candidate; layout still rejects feature-state. Text enum guide.
08.37: Shared icon-offset accepts x,y constants/array expressions in logical pixels, multiplied by actual icon-size and rotated with icon-rotate. Icon-anchor accepts string expressions for nine anchors. Attribute/global-state updates refresh drawing, collision and queries. Offset guide.
08.38: allow-overlap/ignore-placement/optional accept boolean expressions; icon/text padding accepts numeric expressions in0..128. Policies evaluate per feature. Shared dynamic auto ordering scope is documented in the policy guide.
08.39: Shared symbol layout uses floor(zoom), while paint remains fractional. Icon/text/collision/order/missing-image demand shares this rule. See layout zoom.
Shared icon-image supports availability-aware typed images, reported by commonIconImageExpressions=true. Missing image values are actual null for coalesce; plain strings and empty strings keep their existing semantics. Lexical/lazy scope and the8192-step budget are reused; RGBA/SDF parameters and queries remain unchanged. Only attempted names contribute missing notices, and native/WASM image candidates validate before commit. See icon image expressions. Patterns, downloads, URL-style expression domains and3D remain outside this capability.
Shared planar fill-pattern supports one uniform RGBA pattern per layer, reported by commonFillPatternsUniform. It supports image/coalesce/lexical variables and integer zoom/global-state, with a world-anchored CSS period. It ignores fill-color, multiplies fill-opacity, draws/hits nothing when missing, and restores solid fill/outlines on null. Current image dimensions are powers of two from2 through512; per-feature, SDF, transitions, line and3D combinations remain unsupported. See fill patterns.
Shared number-format supports five standard options for en-US/zh-CN/de-DE/fr-FR/ja-JP, defaults to en-US and reports commonNumberFormat. Option expressions, currency precision,45 simple units/compound units,negative zero,rounding and atomic failure share one implementation. CLDR48.2 license/source records ship with the SDK;other locales and collator remain pending. See number formatting.
Shared typed collator supports five locales,three options,four sensitivities,six comparison third arguments,typeof and resolved-locale,reported by commonCollatorSearch. It uses real Unicode search data without JSON impersonation;dynamic scopes/options,budgets and atomic failures share common semantics. Existing two-argument comparison stays compatible. See locale-aware comparisons;other locales,complete styles and device acceptance remain pending.
Shared 2D line-dasharray supports 1–16 nonnegative width multiples or shared expressions, with a positive cycle and the existing 100 CSSpx per-entry / 24px dynamic-width preflight. Odd arrays join their last and first painted segments; dash zoom uses integer values. Property/state/global/lexical/branch updates preserve identity; invalid candidates preserve old content. Queries retain whole-line envelopes. Capability commonLineDashArrays; full pitched/globe dashes and cap/join options remain pending.
Shared scripts import Evented from sqsmap and use local map.fire/setEventedParent/custom events. Mixed map/Evented parent chains, upward listens, once/unsubscription and terminal/session cleanup follow custom events. Metadata cannot replace type/target; project budgets and actual host-event availability remain explicit. Local events neither mutate the map nor provide UI.
Shared line symbols (commonLineSymbols)
A matching development SDK returning commonLineSymbols=true supports symbol-placement=line/line-center for original GeoJSON/MVT line parts in the shared planar Mercator view (zero pitch/roll, no terrain/extrusion). symbol-spacing defaults to 250 CSS pixels; text-max-angle to 45 degrees; text-keep-upright/icon-keep-upright to true/false. map/auto follows road tangents, viewport lays out the whole label horizontally, and viewport-glyph places text centers along the curve while keeping glyph axes oriented to the viewport. Explicit multiline labels reject. Existing PBF, RGBA/SDF, format, image fitting, sorting, collision and optional-group semantics apply; text that cannot fit follows text-optional and cannot leave an icon when that text is required.
Actual glyph quads and original feature/part/source identities drive placement, collision and queries. Generated anchors never modify source data. Invalid resolved symbol paint in a line candidate explicitly rejects and retains the previous frame; existing point fallback semantics remain. Legal glyph fallback keeps its existing contract. An asynchronous candidate exceeding actual template/glyph budgets rejects; legal fallback is not presented as a resource failure. MVT uses original-part arc lengths and half-open target ownership, preserving parent fallback and world copies. Radial extent relative to an anchor is limited to 1024 CSS pixels; unknown tile coverage expands by that bound while retaining 64-tile/32-request limits. Cross-tile geometry stitching, a globally consistent repetition phase along the entire road, complex shaping, tilted/globe/terrain line placement, device/external-platform acceptance and formal release remain pending.
Common paint transitions and planar playback/media
With a matching core exposing commonPaintTransitions, root transition and property-transition objects support the42 implemented uniform numeric/color/vec2 properties. Duration/delay default to300/0ms and each is bounded by3600000. Per-property fields independently override root values; controls affect subsequent retargets. Reads expose target declarations while display/query share actual-time samples. Interrupted priors keep their original clocks; compatible/no-op diffs retain identities and applicable timelines. Data/feature-state targets remain immediate. Image/dash/pattern crossfade, layout/enums/nonzeroLight and unsupported properties do not gain transitions. The current/candidate history budget, failure declaration/display distinction and full property table are documented inCommon paint transitions.
Only zero-pitch/roll Mercator views allow the newly accepted simple playback-line/media composition, with real layer order and original scene owner/playback clock. Paint writes, including controls, to a playing or paused layer retaining its visual returnCONFLICT until playback is stopped; starting playback on a layer with an active paint curve also conflicts. Other layers may transition. Existing topology/offset/gap/blur/pattern/gradient/globe/terrain animation restrictions remain. Older references to pending complete transitions do not exclude this conditional uniform-property batch; image crossfade and full style support remain pending. External platforms, devices, mobileGIS/iOS and formal publication still require acceptance.