Skip to content

自定义图层

除了内置图层,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-keynumber-控制图层的排序顺序,根据该值对要素按升序排序。排序键值越大的要素,显示优先级越高
visibility"visible" | "none""visible"控制图层的可见性

Paint 属性

属性类型默认值说明
circle-radiusnumber5控制圆的半径
circle-colorcolor"#000000"控制圆的填充颜色
circle-blurnumber0控制圆的模糊度
circle-opacitynumber1控制圆的透明度(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-widthnumber0控制圆形的描边宽度
circle-stroke-colorcolor"#000000"控制圆形的描边颜色
circle-stroke-opacitynumber1控制圆形的描边透明度(0-1)

Line 图层属性

Layout 属性

属性类型默认值说明
line-cap"butt" | "round" | "square""butt"控制线段的端点样式。butt:线段两端为平直的;round:线段两端为圆形的;square:线段两端为正方形的
line-join"miter" | "round" | "bevel""miter"控制线段的连接样式。miter:线段连接处为直角平切样式;round:线段连接处为圆形;bevel:线段连接处为尖锐的斜角
line-miter-limitnumber2控制线段连接处斜角的最大角度
line-round-limitnumber1.05控制线段连接处圆形的最大角度
line-sort-keynumber-控制线段在图层中的绘制顺序,根据该值对要素按升序排序。排序键值越大的要素,显示优先级越高
visibility"visible" | "none""visible"控制图层的可见性

Paint 属性

属性类型默认值说明
line-blurnumber0控制线段的模糊度
line-opacitynumber1控制线段的透明度(0-1)
line-translate[number, number][0, 0]控制线段的平移
line-translate-anchor"map" | "viewport""map"控制线段的平移锚点
line-colorcolor"#000000"控制线段的颜色
line-widthnumber1控制线段的宽度
line-gap-widthnumber0控制线段的间距
line-offsetnumber0控制线段的偏移量。正值会使线条相对于其方向向右偏移,负值则向左偏移
line-dasharraynumber[]-控制线段的虚线样式,该属性会被 line-pattern 属性禁用。用于定义组成虚线样式的"交替短划线和间隔的长度"。数组中各长度值后续会按线宽缩放
line-patternresolvedImage-控制线段的图案,指定用于绘制"图像线条"的精灵图中的图像名称。若需实现无缝图案效果,图像宽度必须是 2 的幂次方(2、4、8、…、512 像素)
line-gradientcolor-控制线段的渐变,该属性会被 line-dasharrayline-pattern 禁用,仅支持 GeoJSON 类型数据源

Fill 图层属性

Layout 属性

属性类型默认值说明
fill-sort-keynumber-控制图层的排序顺序,根据该值对要素按升序排序。排序键值越大的要素,显示优先级越高
visibility"visible" | "none""visible"控制图层的可见性

Paint 属性

属性类型默认值说明
fill-antialiasbooleantrue控制填充的抗锯齿效果
fill-opacitynumber1控制填充的透明度(0-1)
fill-colorcolor"#000000"控制填充的颜色,该属性会被 fill-pattern 禁用
fill-outline-colorcolor"#000000"控制填充的边框颜色,该属性会被 fill-pattern 禁用,且需要 fill-antialiastrue
fill-translate[number, number][0, 0]控制填充的平移
fill-translate-anchor"map" | "viewport""map"控制填充的平移锚点
fill-patternresolvedImage-控制填充的图案,指定用于绘制"图像填充"的精灵图中的图像名称。若需实现无缝图案效果,图像宽度必须是 2 的幂次方(2、4、8、…、512 像素)

Symbol 图层属性

Layout 属性

符号放置
属性类型默认值说明
symbol-placement"line" | "line-center" | "point""point"符号放置位置。point 表示放置在几何图形的所在位置点上;line 将沿几何图形的线条放置,仅可用于 LineString 和 Polygon 几何图形;line-center 表示符号放置在线中心上,仅可用于 LineString 和 Polygon 几何图形
symbol-spacingnumber250符号间隔(像素),该属性要求 symbol-placement 必须设为 line
symbol-avoid-edgesbooleanfalse符号边缘避让。若设为 true,symbols(如图标、标签)将不会跨越矢量瓦片边界绘制,以避免瓦片间的符号相互碰撞
symbol-sort-keynumber-控制图层的排序顺序,根据该值对要素按升序排序。排序键值越大的要素,显示优先级越高
图标属性
属性类型默认值说明
icon-imageresolvedImage-图标图片,用于绘制图像背景的 sprite 中的图片名称
icon-sizenumber1控制图标大小
icon-rotatenumber0图标旋转角度,要求 icon-image 属性
icon-paddingpadding2图标内边距,要求 icon-image 属性
icon-keep-uprightbooleanfalse若为 true,图标可能会翻转以防止上下颠倒渲染。要求 icon-image 属性、icon-rotation-alignmentmap,且 symbol-placementlineline-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-placementpoint 时,图标按东西方向对齐;当 symbol-placementlineline-center 时,图标 x 轴与线条对齐。viewport:无论 symbol-placement 的值如何,图标 x 轴与视口 x 轴对齐。auto:当 symbol-placementpoint 时,等同于 viewport;当 symbol-placementlineline-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-imagetext-field 属性,且 icon-text-fitbothwidthheight
icon-allow-overlapbooleanfalse控制图标是否允许压盖,需要 icon-image,被 icon-overlap 禁用。如果设置为 true,图标将允许压盖
icon-overlap"never" | "always" | "cooperative""never"控制图标重叠模式,需要 icon-imagenever:如果该图标与之前绘制的任何其他符号发生重叠,它将会被隐藏;always:即使该图标与之前绘制的任何符号发生重叠,它也会显示出来;cooperative:如果图标与先前绘制的符号发生碰撞,则会检查该符号的重叠模式
icon-ignore-placementbooleanfalse用于控制图标是否被其他图标或文本覆盖。如果设置为 true,即使其他符号与图标重叠,它们也可能是可见的
icon-optionalbooleanfalse用于控制图标是否可见。如果设置为 true,当图标与其他符号发生冲突而文本未冲突时,文本将显示但不带其对应的图标
文本属性
属性类型默认值说明
text-fieldstring""文字内容
text-fontstring[]["Open Sans Regular", "Arial Unicode MS Regular"]文字字体
text-sizenumber16文字大小
text-max-widthnumber10文字最大宽度
text-line-heightnumber1.2文字行高
text-letter-spacingnumber0文字间距
text-justify"auto" | "left" | "center" | "right""center"文字对齐方式。auto:文本朝向锚点位置对齐;left:文本左对齐;center:文本居中对齐;right:文本右对齐
text-rotation-alignment"map" | "viewport" | "viewport-glyph" | "auto""auto"文字旋转模式。map:当 symbol-placementpoint 时,文本按东西方向对齐;当 symbol-placementlineline-center 时,文本 x 轴与线条对齐。viewport:无论 symbol-placement 的值如何,字形 x 轴与视口 x 轴对齐。viewport-glyph:当 symbol-placementpoint 时,文本与视口 x 轴对齐;当 symbol-placementlineline-center 时,字形与视口 x 轴对齐并沿线条放置。auto:当 symbol-placementpoint 时,等同于 viewport;当 symbol-placementlineline-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-offsetnumber0文字的径向偏移量(单位:em),在符号锚点方向上。要求 text-field 属性。与 text-variable-anchor 结合使用时很有用,如果存在 text-offset,则默认使用二维 text-offset
text-variable-anchorstring[]-可变文字锚点位置数组,用于增加在地图上放置高优先级标签的机会。渲染器将按顺序尝试在每个位置放置标签,然后再移动到下一个标签。要求 text-field 属性,且 symbol-placementpoint
text-variable-anchor-offsetarray-可变文字锚点位置数组,每个位置都配有一个偏移值。要求 text-field 属性,且 symbol-placementpoint。数组长度必须为偶数,并在枚举和点条目之间交替
text-rotatenumber0文字旋转角度(单位:度),顺时针旋转。要求 text-field 属性
text-transform"none" | "uppercase" | "lowercase""none"文字大小写转换,类似于 CSS 的 text-transform 属性。none:不改变文字;uppercase:强制所有字母显示为大写;lowercase:强制所有字母显示为小写。要求 text-field 属性
text-paddingnumber2文字边界框周围用于检测符号碰撞的额外区域大小(单位:像素)。要求 text-field 属性
text-max-anglenumber45相邻字符之间的最大角度变化(单位:度)。要求 text-field 属性,且 symbol-placementlineline-center
text-writing-modestring[]-控制符号的方向。要求 text-field 属性,且 symbol-placementpoint
text-keep-uprightbooleantrue如果为 true,文字可能会垂直翻转以防止倒置渲染。要求 text-field 属性、text-rotation-alignmentmap,且 symbol-placementlineline-center
text-allow-overlapbooleanfalse控制文字是否允许压盖,需要 text-field,被 text-overlap 禁用。如果设置为 true,文字将允许压盖
text-overlap"never" | "always" | "cooperative""never"控制文字重叠模式,需要 text-fieldnever:如果该文字与之前绘制的任何其他符号发生重叠,它将会被隐藏;always:即使该文字与之前绘制的任何符号发生重叠,它也会显示出来;cooperative:如果文字与先前绘制的符号发生碰撞,则会检查该符号的重叠模式
text-ignore-placementbooleanfalse用于控制文字是否被其他图标或文本覆盖。如果设置为 true,即使其他符号与文字重叠,它们也可能是可见的
text-optionalbooleanfalse用于控制文字是否可见。如果设置为 true,当文字与其他符号发生冲突而图标未冲突时,图标将显示但不带其对应的文字
visibility"visible" | "none""visible"控制图层的可见性

Paint 属性

属性类型默认值说明
text-colorcolor"#000000"文字颜色,要求 text-field 属性
text-halo-colorcolor"rgba(0, 0, 0, 0)"文字光晕颜色,有助于文字从背景中突出显示,要求 text-field 属性
text-halo-widthnumber0文字光晕宽度(单位:像素),要求 text-field 属性。最大文字光晕宽度为字体大小的 1/4
text-halo-blurnumber0文字光晕的淡出距离(单位:像素),要求 text-field 属性
text-opacitynumber1文字透明度(0-1),要求 text-field 属性
text-translate[number, number][0, 0]文字锚点从其原始位置的移动距离(单位:像素),要求 text-field 属性。正值表示向右和向下移动,负值表示向左和向上移动
text-translate-anchor"map" | "viewport""map"控制 text-translate 的参考坐标系,要求 text-fieldtext-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();

注意事项

  1. 数据源先于图层: 必须先添加数据源,再添加图层
  2. 图层ID唯一: 每个图层必须有唯一的 ID
  3. 样式兼容性: 确保样式属性与图层类型匹配
  4. 性能优化: 大量数据时考虑使用 Vector Tiles 或聚合
  5. 内存管理: 不需要的图层和数据源应及时删除