自定义图层
除了内置图层,SDK 还支持添加自定义图层,可以灵活地在地图上显示自己的数据。
添加自定义图层
基础用法
javascript
// 1. 添加数据源
sdk.addSource("custom-source", {
type: "geojson",
data: {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: {
type: "Point",
coordinates: [116.3974, 39.9093],
},
properties: {
name: "自定义点",
},
},
],
},
});
// 2. 添加图层
sdk.addLayer({
id: "custom-layer",
source: "custom-source",
type: "circle",
paint: {
"circle-radius": 8,
"circle-color": "#ff0000",
},
});使用 LayerManager
javascript
// 使用 LayerManager 添加图层
const layerId = sdk.layerManager.addLayer({
id: "custom-layer",
source: "custom-source",
type: "circle",
paint: {
"circle-radius": 8,
"circle-color": "#ff0000",
},
});
console.log("图层ID:", layerId);图层类型
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
// 先注册图标
sdk.registerIcon("custom-icon", iconImage, {
pixelRatio: 1,
});
// 添加符号图层
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,
},
});数据源类型
GeoJSON 源
javascript
sdk.addSource("geojson-source", {
type: "geojson",
data: {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: {
type: "Point",
coordinates: [116.3974, 39.9093],
},
properties: {},
},
],
},
});Vector Tile 源
javascript
sdk.addSource("vector-source", {
type: "vector",
tiles: [
"https://example.com/tiles/{z}/{x}/{y}.pbf",
],
minzoom: 0,
maxzoom: 14,
});Raster Tile 源
javascript
sdk.addSource("raster-source", {
type: "raster",
tiles: [
"https://example.com/tiles/{z}/{x}/{y}.png",
],
tileSize: 256,
});Image 源
javascript
sdk.addSource("image-source", {
type: "image",
url: "https://example.com/image.jpg",
coordinates: [
[116.0, 40.0], // 左上
[117.0, 40.0], // 右上
[117.0, 39.0], // 右下
[116.0, 39.0], // 左下
],
});Video 源
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],
],
});图层样式
Circle 图层属性
Layout 属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
circle-sort-key | number | - | 控制图层的排序顺序,根据该值对要素按升序排序。排序键值越大的要素,显示优先级越高 |
visibility | "visible" | "none" | "visible" | 控制图层的可见性 |
Paint 属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
circle-radius | number | 5 | 控制圆的半径 |
circle-color | color | "#000000" | 控制圆的填充颜色 |
circle-blur | number | 0 | 控制圆的模糊度 |
circle-opacity | number | 1 | 控制圆的透明度(0-1) |
circle-translate | [number, number] | [0, 0] | 控制圆的偏移量 |
circle-translate-anchor | "map" | "viewport" | "map" | 控制圆的平移锚点。map 表示相对于地图进行了平移,viewport 表示相对于视口进行了平移 |
circle-pitch-scale | "map" | "viewport" | "map" | 控制地图倾斜时,圆的缩放行为。map 圆形根据其与相机的视觉距离进行缩放,viewport 圆形不随地图倾斜缩放 |
circle-pitch-alignment | "map" | "viewport" | "map" | 控制地图倾斜时,圆的贴合方式。map 圆与地图平面对齐,viewport 圆形会与视口对齐 |
circle-stroke-width | number | 0 | 控制圆形的描边宽度 |
circle-stroke-color | color | "#000000" | 控制圆形的描边颜色 |
circle-stroke-opacity | number | 1 | 控制圆形的描边透明度(0-1) |
Line 图层属性
Layout 属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
line-cap | "butt" | "round" | "square" | "butt" | 控制线段的端点样式。butt:线段两端为平直的;round:线段两端为圆形的;square:线段两端为正方形的 |
line-join | "miter" | "round" | "bevel" | "miter" | 控制线段的连接样式。miter:线段连接处为直角平切样式;round:线段连接处为圆形;bevel:线段连接处为尖锐的斜角 |
line-miter-limit | number | 2 | 控制线段连接处斜角的最大角度 |
line-round-limit | number | 1.05 | 控制线段连接处圆形的最大角度 |
line-sort-key | number | - | 控制线段在图层中的绘制顺序,根据该值对要素按升序排序。排序键值越大的要素,显示优先级越高 |
visibility | "visible" | "none" | "visible" | 控制图层的可见性 |
Paint 属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
line-blur | number | 0 | 控制线段的模糊度 |
line-opacity | number | 1 | 控制线段的透明度(0-1) |
line-translate | [number, number] | [0, 0] | 控制线段的平移 |
line-translate-anchor | "map" | "viewport" | "map" | 控制线段的平移锚点 |
line-color | color | "#000000" | 控制线段的颜色 |
line-width | number | 1 | 控制线段的宽度 |
line-gap-width | number | 0 | 控制线段的间距 |
line-offset | number | 0 | 控制线段的偏移量。正值会使线条相对于其方向向右偏移,负值则向左偏移 |
line-dasharray | number[] | - | 控制线段的虚线样式,该属性会被 line-pattern 属性禁用。用于定义组成虚线样式的"交替短划线和间隔的长度"。数组中各长度值后续会按线宽缩放 |
line-pattern | resolvedImage | - | 控制线段的图案,指定用于绘制"图像线条"的精灵图中的图像名称。若需实现无缝图案效果,图像宽度必须是 2 的幂次方(2、4、8、…、512 像素) |
line-gradient | color | - | 控制线段的渐变,该属性会被 line-dasharray 和 line-pattern 禁用,仅支持 GeoJSON 类型数据源 |
Fill 图层属性
Layout 属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
fill-sort-key | number | - | 控制图层的排序顺序,根据该值对要素按升序排序。排序键值越大的要素,显示优先级越高 |
visibility | "visible" | "none" | "visible" | 控制图层的可见性 |
Paint 属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
fill-antialias | boolean | true | 控制填充的抗锯齿效果 |
fill-opacity | number | 1 | 控制填充的透明度(0-1) |
fill-color | color | "#000000" | 控制填充的颜色,该属性会被 fill-pattern 禁用 |
fill-outline-color | color | "#000000" | 控制填充的边框颜色,该属性会被 fill-pattern 禁用,且需要 fill-antialias 为 true |
fill-translate | [number, number] | [0, 0] | 控制填充的平移 |
fill-translate-anchor | "map" | "viewport" | "map" | 控制填充的平移锚点 |
fill-pattern | resolvedImage | - | 控制填充的图案,指定用于绘制"图像填充"的精灵图中的图像名称。若需实现无缝图案效果,图像宽度必须是 2 的幂次方(2、4、8、…、512 像素) |
Symbol 图层属性
Layout 属性
符号放置
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
symbol-placement | "line" | "line-center" | "point" | "point" | 符号放置位置。point 表示放置在几何图形的所在位置点上;line 将沿几何图形的线条放置,仅可用于 LineString 和 Polygon 几何图形;line-center 表示符号放置在线中心上,仅可用于 LineString 和 Polygon 几何图形 |
symbol-spacing | number | 250 | 符号间隔(像素),该属性要求 symbol-placement 必须设为 line |
symbol-avoid-edges | boolean | false | 符号边缘避让。若设为 true,symbols(如图标、标签)将不会跨越矢量瓦片边界绘制,以避免瓦片间的符号相互碰撞 |
symbol-sort-key | number | - | 控制图层的排序顺序,根据该值对要素按升序排序。排序键值越大的要素,显示优先级越高 |
图标属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
icon-image | resolvedImage | - | 图标图片,用于绘制图像背景的 sprite 中的图片名称 |
icon-size | number | 1 | 控制图标大小 |
icon-rotate | number | 0 | 图标旋转角度,要求 icon-image 属性 |
icon-padding | padding | 2 | 图标内边距,要求 icon-image 属性 |
icon-keep-upright | boolean | false | 若为 true,图标可能会翻转以防止上下颠倒渲染。要求 icon-image 属性、icon-rotation-alignment 为 map,且 symbol-placement 为 line 或 line-center |
icon-offset | [number, number] | [0, 0] | 图标偏移量,要求 icon-image 属性 |
icon-anchor | "center" | "left" | "right" | "top" | "bottom" | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "center" | 图标锚点,要求 icon-image 属性 |
icon-rotation-alignment | "map" | "viewport" | "auto" | "map" | 控制图标旋转的对齐方式。map:当 symbol-placement 为 point 时,图标按东西方向对齐;当 symbol-placement 为 line 或 line-center 时,图标 x 轴与线条对齐。viewport:无论 symbol-placement 的值如何,图标 x 轴与视口 x 轴对齐。auto:当 symbol-placement 为 point 时,等同于 viewport;当 symbol-placement 为 line 或 line-center 时,等同于 map |
icon-pitch-alignment | "map" | "viewport" | "auto" | "auto" | 图标的贴地模式。map:图标与地图平行;viewport:图标与视口平行;auto:自动匹配 icon-rotation-alignment 的值 |
icon-text-fit | "none" | "width" | "height" | "both" | "none" | 控制图标文本的适应性。none:不进行任何调整;width:图标在 x 维度上缩放以适应文本宽度;height:图标在 y 维度上缩放以适应文本高度;both:图标在 x 和 y 维度上都缩放 |
icon-text-fit-padding | [number, number, number, number] | [0, 0, 0, 0] | 控制图标文本的适应性,要求 icon-image、text-field 属性,且 icon-text-fit 为 both、width 或 height |
icon-allow-overlap | boolean | false | 控制图标是否允许压盖,需要 icon-image,被 icon-overlap 禁用。如果设置为 true,图标将允许压盖 |
icon-overlap | "never" | "always" | "cooperative" | "never" | 控制图标重叠模式,需要 icon-image。never:如果该图标与之前绘制的任何其他符号发生重叠,它将会被隐藏;always:即使该图标与之前绘制的任何符号发生重叠,它也会显示出来;cooperative:如果图标与先前绘制的符号发生碰撞,则会检查该符号的重叠模式 |
icon-ignore-placement | boolean | false | 用于控制图标是否被其他图标或文本覆盖。如果设置为 true,即使其他符号与图标重叠,它们也可能是可见的 |
icon-optional | boolean | false | 用于控制图标是否可见。如果设置为 true,当图标与其他符号发生冲突而文本未冲突时,文本将显示但不带其对应的图标 |
文本属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
text-field | string | "" | 文字内容 |
text-font | string[] | ["Open Sans Regular", "Arial Unicode MS Regular"] | 文字字体 |
text-size | number | 16 | 文字大小 |
text-max-width | number | 10 | 文字最大宽度 |
text-line-height | number | 1.2 | 文字行高 |
text-letter-spacing | number | 0 | 文字间距 |
text-justify | "auto" | "left" | "center" | "right" | "center" | 文字对齐方式。auto:文本朝向锚点位置对齐;left:文本左对齐;center:文本居中对齐;right:文本右对齐 |
text-rotation-alignment | "map" | "viewport" | "viewport-glyph" | "auto" | "auto" | 文字旋转模式。map:当 symbol-placement 为 point 时,文本按东西方向对齐;当 symbol-placement 为 line 或 line-center 时,文本 x 轴与线条对齐。viewport:无论 symbol-placement 的值如何,字形 x 轴与视口 x 轴对齐。viewport-glyph:当 symbol-placement 为 point 时,文本与视口 x 轴对齐;当 symbol-placement 为 line 或 line-center 时,字形与视口 x 轴对齐并沿线条放置。auto:当 symbol-placement 为 point 时,等同于 viewport;当 symbol-placement 为 line 或 line-center 时,等同于 map |
text-pitch-alignment | "map" | "viewport" | "auto" | "auto" | 文字贴地模式。map:文字与地图平行;viewport:文字与视口平行;auto:自动匹配 text-rotation-alignment 的值 |
text-anchor | "center" | "left" | "right" | "top" | "bottom" | "top-left" | "top-right" | "bottom-left" | "bottom-right" | "center" | 文字锚点位置,指定文字的哪一部分最靠近锚点。center:文字中心;left:左侧;right:右侧;top:顶部;bottom:底部;top-left:左上角;top-right:右上角;bottom-left:左下角;bottom-right:右下角。要求 text-field 属性,被 text-variable-anchor 禁用 |
text-offset | [number, number] | [0, 0] | 文字偏移量(单位:em),要求 text-field 属性,被 text-radial-offset 禁用。正值表示向右和向下偏移,负值表示向左和向上偏移 |
text-radial-offset | number | 0 | 文字的径向偏移量(单位:em),在符号锚点方向上。要求 text-field 属性。与 text-variable-anchor 结合使用时很有用,如果存在 text-offset,则默认使用二维 text-offset |
text-variable-anchor | string[] | - | 可变文字锚点位置数组,用于增加在地图上放置高优先级标签的机会。渲染器将按顺序尝试在每个位置放置标签,然后再移动到下一个标签。要求 text-field 属性,且 symbol-placement 为 point |
text-variable-anchor-offset | array | - | 可变文字锚点位置数组,每个位置都配有一个偏移值。要求 text-field 属性,且 symbol-placement 为 point。数组长度必须为偶数,并在枚举和点条目之间交替 |
text-rotate | number | 0 | 文字旋转角度(单位:度),顺时针旋转。要求 text-field 属性 |
text-transform | "none" | "uppercase" | "lowercase" | "none" | 文字大小写转换,类似于 CSS 的 text-transform 属性。none:不改变文字;uppercase:强制所有字母显示为大写;lowercase:强制所有字母显示为小写。要求 text-field 属性 |
text-padding | number | 2 | 文字边界框周围用于检测符号碰撞的额外区域大小(单位:像素)。要求 text-field 属性 |
text-max-angle | number | 45 | 相邻字符之间的最大角度变化(单位:度)。要求 text-field 属性,且 symbol-placement 为 line 或 line-center |
text-writing-mode | string[] | - | 控制符号的方向。要求 text-field 属性,且 symbol-placement 为 point |
text-keep-upright | boolean | true | 如果为 true,文字可能会垂直翻转以防止倒置渲染。要求 text-field 属性、text-rotation-alignment 为 map,且 symbol-placement 为 line 或 line-center |
text-allow-overlap | boolean | false | 控制文字是否允许压盖,需要 text-field,被 text-overlap 禁用。如果设置为 true,文字将允许压盖 |
text-overlap | "never" | "always" | "cooperative" | "never" | 控制文字重叠模式,需要 text-field。never:如果该文字与之前绘制的任何其他符号发生重叠,它将会被隐藏;always:即使该文字与之前绘制的任何符号发生重叠,它也会显示出来;cooperative:如果文字与先前绘制的符号发生碰撞,则会检查该符号的重叠模式 |
text-ignore-placement | boolean | false | 用于控制文字是否被其他图标或文本覆盖。如果设置为 true,即使其他符号与文字重叠,它们也可能是可见的 |
text-optional | boolean | false | 用于控制文字是否可见。如果设置为 true,当文字与其他符号发生冲突而图标未冲突时,图标将显示但不带其对应的文字 |
visibility | "visible" | "none" | "visible" | 控制图层的可见性 |
Paint 属性
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
text-color | color | "#000000" | 文字颜色,要求 text-field 属性 |
text-halo-color | color | "rgba(0, 0, 0, 0)" | 文字光晕颜色,有助于文字从背景中突出显示,要求 text-field 属性 |
text-halo-width | number | 0 | 文字光晕宽度(单位:像素),要求 text-field 属性。最大文字光晕宽度为字体大小的 1/4 |
text-halo-blur | number | 0 | 文字光晕的淡出距离(单位:像素),要求 text-field 属性 |
text-opacity | number | 1 | 文字透明度(0-1),要求 text-field 属性 |
text-translate | [number, number] | [0, 0] | 文字锚点从其原始位置的移动距离(单位:像素),要求 text-field 属性。正值表示向右和向下移动,负值表示向左和向上移动 |
text-translate-anchor | "map" | "viewport" | "map" | 控制 text-translate 的参考坐标系,要求 text-field 和 text-translate 属性。map:文字相对于地图进行平移;viewport:文字相对于视口进行平移 |
Paint 属性示例
javascript
sdk.addLayer({
id: "styled-layer",
source: "source-id",
type: "circle",
paint: {
// 基础属性
"circle-radius": 10,
"circle-color": "#ff0000",
"circle-opacity": 0.8,
// 描边属性
"circle-stroke-width": 2,
"circle-stroke-color": "#ffffff",
// 模糊属性
"circle-blur": 0,
},
});Layout 属性示例
javascript
sdk.addLayer({
id: "layout-layer",
source: "source-id",
type: "symbol",
layout: {
// 可见性
visibility: "visible", // "visible" | "none"
// 图标
"icon-image": "icon-name",
"icon-size": 1,
"icon-rotate": 0,
// 文本
"text-field": ["get", "name"],
"text-font": ["Open Sans Semibold"],
"text-size": 12,
"text-anchor": "center",
},
});数据驱动样式
javascript
// 根据属性值设置颜色
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,
],
},
});图层顺序
指定插入位置
javascript
// 在指定图层之前插入
sdk.addLayer({
id: "new-layer",
source: "source-id",
type: "circle",
}, "existing-layer-id"); // 在 existing-layer-id 之前
// 在指定图层之后插入
sdk.addLayer({
id: "new-layer",
source: "source-id",
type: "circle",
}, "existing-layer-id", "after");使用 beforeId
javascript
sdk.addLayer({
id: "new-layer",
source: "source-id",
type: "circle",
beforeId: "existing-layer-id",
});更新图层
更新样式
javascript
// 更新 paint 属性
sdk.setPaintProperty("layer-id", "circle-color", "#00ff00");
// 更新 layout 属性
sdk.setLayoutProperty("layer-id", "visibility", "none");
// 批量更新
sdk.updateLayerStyle("layer-id", {
paint: {
"circle-color": "#00ff00",
"circle-radius": 12,
},
layout: {
visibility: "visible",
},
});更新数据
javascript
// 更新 GeoJSON 源数据
sdk.getSource("source-id").setData(newGeoJSON);
// 更新 Vector Tile 源
sdk.getSource("source-id").setTiles([
"https://new-url.com/tiles/{z}/{x}/{y}.pbf",
]);删除图层
删除图层
javascript
// 删除图层
sdk.removeLayer("layer-id");
// 使用 LayerManager
sdk.layerManager.removeLayer("layer-id");删除数据源
javascript
// 删除数据源
sdk.removeSource("source-id");图层过滤
使用 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",
},
});动态过滤
javascript
// 更新过滤器
sdk.setFilter("filtered-layer", [
">=",
["get", "population"],
5000000,
]);完整示例
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. 添加 GeoJSON 源
sdk.addSource("custom-points", {
type: "geojson",
data: {
type: "FeatureCollection",
features: [
{
type: "Feature",
geometry: {
type: "Point",
coordinates: [116.3974, 39.9093],
},
properties: {
name: "北京",
type: "city",
population: 21540000,
},
},
{
type: "Feature",
geometry: {
type: "Point",
coordinates: [121.4737, 31.2304],
},
properties: {
name: "上海",
type: "city",
population: 24870000,
},
},
],
},
});
// 2. 添加圆形图层
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. 添加标签图层
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. 添加点击事件
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>人口: ${feature.properties.population.toLocaleString()}</p>
`)
.addTo(sdk.map);
});
}
initMap();注意事项
- 数据源先于图层: 必须先添加数据源,再添加图层
- 图层ID唯一: 每个图层必须有唯一的 ID
- 样式兼容性: 确保样式属性与图层类型匹配
- 性能优化: 大量数据时考虑使用 Vector Tiles 或聚合
- 内存管理: 不需要的图层和数据源应及时删除
