Custom Layers
In addition to built-in layers, the SDK also supports adding custom layers, allowing you to flexibly display your own data on the map.
Adding Custom Layers
Basic Usage
javascript
// 1. Add data source
sdk.addSource("custom-source", {
type: "geojson",
data: {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: {
type: "Point",
coordinates: [116.3974, 39.9093],
},
properties: {
name: "Custom Point",
},
},
],
},
});
// 2. Add layer
sdk.addLayer({
id: "custom-layer",
source: "custom-source",
type: "circle",
paint: {
"circle-radius": 8,
"circle-color": "#ff0000",
},
});Using LayerManager
javascript
// Use LayerManager to add layer
const layerId = sdk.layerManager.addLayer({
id: "custom-layer",
source: "custom-source",
type: "circle",
paint: {
"circle-radius": 8,
"circle-color": "#ff0000",
},
});
console.log("Layer ID:", layerId);Layer Types
Circle
javascript
sdk.addLayer({
id: "circle-layer",
source: "points-source",
type: "circle",
paint: {
"circle-radius": 10,
"circle-color": "#ff0000",
"circle-stroke-width": 2,
"circle-stroke-color": "#ffffff",
"circle-opacity": 0.8,
},
});Line
javascript
sdk.addLayer({
id: "line-layer",
source: "lines-source",
type: "line",
paint: {
"line-color": "#007bff",
"line-width": 2,
"line-opacity": 0.8,
"line-dasharray": [2, 2],
},
});Fill
javascript
sdk.addLayer({
id: "fill-layer",
source: "polygons-source",
type: "fill",
paint: {
"fill-color": "#007bff",
"fill-opacity": 0.5,
"fill-outline-color": "#000000",
},
});Symbol
javascript
// Register icon first
sdk.registerIcon("custom-icon", iconImage, {
pixelRatio: 1,
});
// Add symbol layer
sdk.addLayer({
id: "symbol-layer",
source: "points-source",
type: "symbol",
layout: {
"icon-image": "custom-icon",
"icon-size": 1,
"text-field": ["get", "name"],
"text-font": ["Open Sans Semibold", "Arial Unicode MS Bold"],
"text-size": 12,
},
paint: {
"text-color": "#000000",
},
});Heatmap
javascript
sdk.addLayer({
id: "heatmap-layer",
source: "points-source",
type: "heatmap",
paint: {
"heatmap-weight": 1,
"heatmap-intensity": 1,
"heatmap-color": [
"interpolate",
["linear"],
["heatmap-density"],
0,
"rgba(0,0,255,0)",
0.1,
"royalblue",
0.3,
"cyan",
0.5,
"lime",
0.7,
"yellow",
1,
"red",
],
"heatmap-radius": 30,
"heatmap-opacity": 0.6,
},
});Source Types
GeoJSON Source
javascript
sdk.addSource("geojson-source", {
type: "geojson",
data: {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: {
type: "Point",
coordinates: [116.3974, 39.9093],
},
properties: {},
},
],
},
});Vector Tile Source
javascript
sdk.addSource("vector-source", {
type: "vector",
tiles: [
"https://example.com/tiles/{z}/{x}/{y}.pbf",
],
minzoom: 0,
maxzoom: 14,
});Raster Tile Source
javascript
sdk.addSource("raster-source", {
type: "raster",
tiles: [
"https://example.com/tiles/{z}/{x}/{y}.png",
],
tileSize: 256,
});Image Source
javascript
sdk.addSource("image-source", {
type: "image",
url: "https://example.com/image.jpg",
coordinates: [
[116.0, 40.0], // Top left
[117.0, 40.0], // Top right
[117.0, 39.0], // Bottom right
[116.0, 39.0], // Bottom left
],
});Video Source
javascript
sdk.addSource("video-source", {
type: "video",
urls: [
"https://example.com/video.mp4",
],
coordinates: [
[116.0, 40.0],
[117.0, 40.0],
[117.0, 39.0],
[116.0, 39.0],
],
});Layer Styles
Circle Layer Properties
Layout Properties
| Property | Type | Default | Description |
|---|---|---|---|
circle-sort-key | number | - | Controls layer sort order, sorts features in ascending order by this value. Features with larger sort key values have higher display priority |
visibility | "visible" | "none" | "visible" | Controls layer visibility |
Paint Properties
| Property | Type | Default | Description |
|---|---|---|---|
circle-radius | number | 5 | Controls circle radius |
circle-color | color | "#000000" | Controls circle fill color |
circle-blur | number | 0 | Controls circle blur |
circle-opacity | number | 1 | Controls circle opacity (0-1) |
circle-translate | [number, number] | [0, 0] | Controls circle offset |
circle-translate-anchor | "map" | "viewport" | "map" | Controls circle translate anchor. map means translated relative to map, viewport means translated relative to viewport |
circle-pitch-scale | "map" | "viewport" | "map" | Controls circle scaling behavior when map is tilted. map circles scale based on visual distance from camera, viewport circles don't scale with map tilt |
circle-pitch-alignment | "map" | "viewport" | "map" | Controls circle alignment when map is tilted. map circles align with map plane, viewport circles align with viewport |
circle-stroke-width | number | 0 | Controls circle stroke width |
circle-stroke-color | color | "#000000" | Controls circle stroke color |
circle-stroke-opacity | number | 1 | Controls circle stroke opacity (0-1) |
Line Layer Properties
Layout Properties
| Property | Type | Default | Description |
|---|---|---|---|
line-cap | "butt" | "round" | "square" | "butt" | Controls line cap style. butt: flat ends; round: round ends; square: square ends |
line-join | "miter" | "round" | "bevel" | "miter" | Controls line join style. miter: sharp corner; round: round join; bevel: beveled join |
line-miter-limit | number | 2 | Controls maximum angle at line join |
line-round-limit | number | 1.05 | Controls maximum angle at round join |
line-sort-key | number | - | Controls line drawing order in layer, sorts features in ascending order by this value. Features with larger sort key values have higher display priority |
visibility | "visible" | "none" | "visible" | Controls layer visibility |
Paint Properties
| Property | Type | Default | Description |
|---|---|---|---|
line-blur | number | 0 | Controls line blur |
line-opacity | number | 1 | Controls line opacity (0-1) |
line-translate | [number, number] | [0, 0] | Controls line translation |
line-translate-anchor | "map" | "viewport" | "map" | Controls line translate anchor |
line-color | color | "#000000" | Controls line color |
line-width | number | 1 | Controls line width |
line-gap-width | number | 0 | Controls line gap width |
line-offset | number | 0 | Controls line offset. Positive values offset line to the right relative to its direction, negative values offset to the left |
line-dasharray | number[] | - | Controls line dash pattern, disabled by line-pattern. Defines alternating dash and gap lengths. Array values are scaled by line width |
line-pattern | resolvedImage | - | Controls line pattern, specifies image name in sprite for drawing image lines. For seamless patterns, image width must be power of 2 (2, 4, 8, ..., 512 pixels) |
line-gradient | color | - | Controls line gradient, disabled by line-dasharray and line-pattern, only supports GeoJSON type sources |
Fill Layer Properties
Layout Properties
| Property | Type | Default | Description |
|---|---|---|---|
fill-sort-key | number | - | Controls layer sort order, sorts features in ascending order by this value. Features with larger sort key values have higher display priority |
visibility | "visible" | "none" | "visible" | Controls layer visibility |
Paint Properties
| Property | Type | Default | Description |
|---|---|---|---|
fill-antialias | boolean | true | Controls fill antialiasing |
fill-opacity | number | 1 | Controls fill opacity (0-1) |
fill-color | color | "#000000" | Controls fill color, disabled by fill-pattern |
fill-outline-color | color | "#000000" | Controls fill outline color, disabled by fill-pattern, requires fill-antialias to be true |
fill-translate | [number, number] | [0, 0] | Controls fill translation |
fill-translate-anchor | "map" | "viewport" | "map" | Controls fill translate anchor |
fill-pattern | resolvedImage | - | Controls fill pattern, specifies image name in sprite for drawing image fill. For seamless patterns, image width must be power of 2 (2, 4, 8, ..., 512 pixels) |
Symbol Layer Properties
Layout Properties
Symbol Placement
| Property | Type | Default | Description |
|---|---|---|---|
symbol-placement | "line" | "line-center" | "point" | "point" | Symbol placement. point places at geometry point; line places along geometry lines, only for LineString and Polygon; line-center places at line center, only for LineString and Polygon |
symbol-spacing | number | 250 | Symbol spacing (pixels), requires symbol-placement to be line |
symbol-avoid-edges | boolean | false | Symbol edge avoidance. If true, symbols (icons, labels) won't cross vector tile boundaries to avoid collisions |
symbol-sort-key | number | - | Controls layer sort order, sorts features in ascending order by this value. Features with larger sort key values have higher display priority |
Icon Properties
| Property | Type | Default | Description |
|---|---|---|---|
icon-image | resolvedImage | - | Icon image, image name in sprite for drawing image background |
icon-size | number | 1 | Controls icon size |
icon-rotate | number | 0 | Icon rotation angle, requires icon-image |
icon-padding | padding | 2 | Icon padding, requires icon-image |
icon-keep-upright | boolean | false | If true, icon may flip to prevent upside-down rendering. Requires icon-image, icon-rotation-alignment to be map, and symbol-placement to be line or line-center |
icon-offset | [number, number] | [0, 0] | Icon offset, requires icon-image |
icon-anchor | "center" | "left" | "right" | "top" | "bottom" | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "center" | Icon anchor, requires icon-image |
icon-rotation-alignment | "map" | "viewport" | "auto" | "map" | Controls icon rotation alignment. map: when symbol-placement is point, icon aligns east-west; when symbol-placement is line or line-center, icon x-axis aligns with line. viewport: icon x-axis aligns with viewport x-axis regardless of symbol-placement. auto: when symbol-placement is point, same as viewport; when symbol-placement is line or line-center, same as map |
icon-pitch-alignment | "map" | "viewport" | "auto" | "auto" | Icon pitch alignment. map: icon parallel to map; viewport: icon parallel to viewport; auto: automatically matches icon-rotation-alignment value |
icon-text-fit | "none" | "width" | "height" | "both" | "none" | Controls icon text fit. none: no adjustment; width: icon scales in x-dimension to fit text width; height: icon scales in y-dimension to fit text height; both: icon scales in both x and y dimensions |
icon-text-fit-padding | [number, number, number, number] | [0, 0, 0, 0] | Controls icon text fit, requires icon-image, text-field, and icon-text-fit to be both, width, or height |
icon-allow-overlap | boolean | false | Controls whether icon allows overlap, requires icon-image, disabled by icon-overlap. If true, icon will allow overlap |
icon-overlap | "never" | "always" | "cooperative" | "never" | Controls icon overlap mode, requires icon-image. never: icon hidden if overlaps with any previously drawn symbol; always: icon shown even if overlaps; cooperative: checks symbol overlap mode if collision occurs |
icon-ignore-placement | boolean | false | Controls whether icon is covered by other icons or text. If true, other symbols may be visible even if overlapping with icon |
icon-optional | boolean | false | Controls icon visibility. If true, when icon conflicts but text doesn't, text shows without corresponding icon |
Text Properties
| Property | Type | Default | Description |
|---|---|---|---|
text-field | string | "" | Text content |
text-font | string[] | ["Open Sans Regular", "Arial Unicode MS Regular"] | Text font |
text-size | number | 16 | Text size |
text-max-width | number | 10 | Text max width |
text-line-height | number | 1.2 | Text line height |
text-letter-spacing | number | 0 | Text letter spacing |
text-justify | "auto" | "left" | "center" | "right" | "center" | Text alignment. auto: text aligns toward anchor; left: left align; center: center align; right: right align |
text-rotation-alignment | "map" | "viewport" | "viewport-glyph" | "auto" | "auto" | Text rotation mode. map: when symbol-placement is point, text aligns east-west; when symbol-placement is line or line-center, text x-axis aligns with line. viewport: glyph x-axis aligns with viewport x-axis regardless of symbol-placement. viewport-glyph: when symbol-placement is point, text aligns with viewport x-axis; when symbol-placement is line or line-center, glyph aligns with viewport x-axis and placed along line. auto: when symbol-placement is point, same as viewport; when symbol-placement is line or line-center, same as map |
text-pitch-alignment | "map" | "viewport" | "auto" | "auto" | Text pitch alignment. map: text parallel to map; viewport: text parallel to viewport; auto: automatically matches text-rotation-alignment value |
text-anchor | "center" | "left" | "right" | "top" | "bottom" | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "center" | Part of the text placed closest to the anchor. center: center of text; left: left side; right: right side; top: top; bottom: bottom; top-left: top-left corner; top-right: top-right corner; bottom-left: bottom-left corner; bottom-right: bottom-right corner. Requires text-field, disabled by text-variable-anchor |
text-offset | [number, number] | [0, 0] | Offset distance of text from its anchor (units: em). Requires text-field, disabled by text-radial-offset. Positive values indicate right and down, negative values indicate left and up |
text-radial-offset | number | 0 | Radial offset of text in the direction of the symbol's anchor (units: em). Requires text-field. Useful in combination with text-variable-anchor, which defaults to using the two-dimensional text-offset if present |
text-variable-anchor | string[] | - | Array of text anchor locations to increase the chance of placing high-priority labels on the map. The renderer will attempt to place the label at each location, in order, before moving onto the next label. Requires text-field and symbol-placement to be point |
text-variable-anchor-offset | array | - | Array of text anchor locations, each paired with an offset value. Requires text-field and symbol-placement to be point. Array length must be even and alternate between enum and point entries |
text-rotate | number | 0 | Rotates the text clockwise (units: degrees). Requires text-field |
text-transform | "none" | "uppercase" | "lowercase" | "none" | Specifies how to capitalize text, similar to CSS text-transform property. none: text not altered; uppercase: forces all letters to uppercase; lowercase: forces all letters to lowercase. Requires text-field |
text-padding | number | 2 | Size of the additional area around the text bounding box used for detecting symbol collisions (units: pixels). Requires text-field |
text-max-angle | number | 45 | Maximum angle change between adjacent characters (units: degrees). Requires text-field and symbol-placement to be line or line-center |
text-writing-mode | string[] | - | Controls a symbol's orientation. Requires text-field and symbol-placement to be point |
text-keep-upright | boolean | true | If true, the text may be flipped vertically to prevent it from being rendered upside-down. Requires text-field, text-rotation-alignment to be map, and symbol-placement to be line or line-center |
text-allow-overlap | boolean | false | Controls whether text allows overlap, requires text-field, disabled by text-overlap. If true, text will allow overlap |
text-overlap | "never" | "always" | "cooperative" | "never" | Controls text overlap mode, requires text-field. never: text hidden if overlaps with any previously drawn symbol; always: text shown even if overlaps; cooperative: checks symbol overlap mode if collision occurs |
text-ignore-placement | boolean | false | Controls whether text is covered by other icons or text. If true, other symbols may be visible even if overlapping with text |
text-optional | boolean | false | Controls text visibility. If true, when text conflicts but icon doesn't, icon will display without corresponding text |
visibility | "visible" | "none" | "visible" | Controls layer visibility |
Paint Properties
| Property | Type | Default | Description |
|---|---|---|---|
text-color | color | "#000000" | Text color, requires text-field |
text-halo-color | color | "rgba(0, 0, 0, 0)" | The color of the text's halo, which helps it stand out from backgrounds, requires text-field |
text-halo-width | number | 0 | Distance of halo to the font outline (units: pixels), requires text-field. Max text halo width is 1/4 of the font-size |
text-halo-blur | number | 0 | The halo's fadeout distance towards the outside (units: pixels), requires text-field |
text-opacity | number | 1 | Text opacity (0-1), requires text-field |
text-translate | [number, number] | [0, 0] | Distance that the text's anchor is moved from its original placement (units: pixels), requires text-field. Positive values indicate right and down, negative values indicate left and up |
text-translate-anchor | "map" | "viewport" | "map" | Controls the frame of reference for text-translate, requires text-field and text-translate. map: text translated relative to map; viewport: text translated relative to viewport |
Paint Property Examples
javascript
sdk.addLayer({
id: "styled-layer",
source: "source-id",
type: "circle",
paint: {
// Basic properties
"circle-radius": 10,
"circle-color": "#ff0000",
"circle-opacity": 0.8,
// Stroke properties
"circle-stroke-width": 2,
"circle-stroke-color": "#ffffff",
// Blur properties
"circle-blur": 0,
},
});Layout Property Examples
javascript
sdk.addLayer({
id: "layout-layer",
source: "source-id",
type: "symbol",
layout: {
// Visibility
visibility: "visible", // "visible" | "none"
// Icon
"icon-image": "icon-name",
"icon-size": 1,
"icon-rotate": 0,
// Text
"text-field": ["get", "name"],
"text-font": ["Open Sans Semibold"],
"text-size": 12,
"text-anchor": "center",
},
});Data-driven Styles
javascript
// Set color based on property value
sdk.addLayer({
id: "data-driven-layer",
source: "source-id",
type: "circle",
paint: {
"circle-color": [
"case",
["==", ["get", "type"], "city"],
"#ff0000",
["==", ["get", "type"], "airport"],
"#0000ff",
"#00ff00",
],
"circle-radius": [
"interpolate",
["linear"],
["get", "population"],
0, 5,
1000000, 20,
],
},
});Layer Order
Specify Insert Position
javascript
// Insert before specified layer
sdk.addLayer({
id: "new-layer",
source: "source-id",
type: "circle",
}, "existing-layer-id"); // Before existing-layer-id
// Insert after specified layer
sdk.addLayer({
id: "new-layer",
source: "source-id",
type: "circle",
}, "existing-layer-id", "after");Using beforeId
javascript
sdk.addLayer({
id: "new-layer",
source: "source-id",
type: "circle",
beforeId: "existing-layer-id",
});Updating Layers
Update Style
javascript
// Update paint property
sdk.setPaintProperty("layer-id", "circle-color", "#00ff00");
// Update layout property
sdk.setLayoutProperty("layer-id", "visibility", "none");
// Batch update
sdk.updateLayerStyle("layer-id", {
paint: {
"circle-color": "#00ff00",
"circle-radius": 12,
},
layout: {
visibility: "visible",
},
});Update Data
javascript
// Update GeoJSON source data
sdk.getSource("source-id").setData(newGeoJSON);
// Update Vector Tile source
sdk.getSource("source-id").setTiles([
"https://new-url.com/tiles/{z}/{x}/{y}.pbf",
]);Deleting Layers
Delete Layer
javascript
// Delete layer
sdk.removeLayer("layer-id");
// Use LayerManager
sdk.layerManager.removeLayer("layer-id");Delete Source
javascript
// Delete source
sdk.removeSource("source-id");Layer Filtering
Using Filter
javascript
sdk.addLayer({
id: "filtered-layer",
source: "source-id",
type: "circle",
filter: [
"all",
[">=", ["get", "population"], 1000000],
["==", ["get", "type"], "city"],
],
paint: {
"circle-radius": 10,
"circle-color": "#ff0000",
},
});Dynamic Filtering
javascript
// Update filter
sdk.setFilter("filtered-layer", [
">=",
["get", "population"],
5000000,
]);Complete Example
javascript
let sdk;
async function initMap() {
sdk = new navMap.MapSDK({
container: "map",
center: [116.39, 39.9],
zoom: 10,
});
sdk.on("loadComplete", () => {
setupCustomLayers();
});
}
function setupCustomLayers() {
// 1. Add GeoJSON source
sdk.addSource("custom-points", {
type: "geojson",
data: {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: {
type: "Point",
coordinates: [116.3974, 39.9093],
},
properties: {
name: "Beijing",
type: "city",
population: 21540000,
},
},
{
type: "Feature",
geometry: {
type: "Point",
coordinates: [121.4737, 31.2304],
},
properties: {
name: "Shanghai",
type: "city",
population: 24870000,
},
},
],
},
});
// 2. Add circle layer
sdk.addLayer({
id: "cities-circle",
source: "custom-points",
type: "circle",
paint: {
"circle-radius": [
"interpolate",
["linear"],
["get", "population"],
0, 5,
10000000, 20,
20000000, 30,
],
"circle-color": [
"case",
[">=", ["get", "population"], 20000000],
"#ff0000",
[">=", ["get", "population"], 10000000],
"#ff8800",
"#00ff00",
],
"circle-opacity": 0.8,
"circle-stroke-width": 2,
"circle-stroke-color": "#ffffff",
},
});
// 3. Add label layer
sdk.addLayer({
id: "cities-label",
source: "custom-points",
type: "symbol",
layout: {
"text-field": ["get", "name"],
"text-font": ["Open Sans Semibold", "Arial Unicode MS Bold"],
"text-size": 12,
"text-offset": [0, 1.5],
},
paint: {
"text-color": "#000000",
"text-halo-color": "#ffffff",
"text-halo-width": 2,
},
});
// 4. Add click event
sdk.on("click", "cities-circle", (e) => {
const feature = e.features[0];
const popup = new navMap.Popup()
.setLngLat(e.lngLat)
.setHTML(`
<h3>${feature.properties.name}</h3>
<p>Population: ${feature.properties.population.toLocaleString()}</p>
`)
.addTo(sdk.map);
});
}
initMap();Notes
- Source Before Layer: Must add source first, then add layer
- Unique Layer ID: Each layer must have a unique ID
- Style Compatibility: Ensure style properties match layer type
- Performance Optimization: Consider using Vector Tiles or clustering for large amounts of data
- Memory Management: Unnecessary layers and sources should be deleted promptly
