唯杰地图 logo唯杰地图
VJMAP
EN

polyline-api

vjmap/references/primitive/polyline-api.md 4.2 KB165 行
原文

本文回答:Polyline / 底座图元的"单独建 source + 图层"写法 —— addGeoJSONSource / addLineLayer / addFillLayer / addCircleLayer / addSymbolLayer。

一、为什么要单独建 source

new vjmap.Polyline({ data }) 会把 source 和 layer 放在一起创建,同一份数据只渲染一种样式。

但如果需要:

  • 同一份 GeoJSON 同时渲染 fill + line + symbol(三种样式共享数据)
  • 程序动态切换不同 layer
  • 多图层共享 source,setData 一次全部更新

→ 需要单独建 source,然后挂多个 layer。

二、addGeoJSONSource

map.addGeoJSONSource("my-src", {
  type: "FeatureCollection",
  features: [...]
});

// 等价于
map.addSource("my-src", {
  type: "geojson",
  data: { type: "FeatureCollection", features: [...] }
});

常用选项:

map.addSource("my-src", {
  type: "geojson",
  data: geojson,
  generateId: true,       // 自动生成 feature.id(feature-state 要用)
  cluster: true,          // 点聚合
  clusterRadius: 50,
  clusterMaxZoom: 14,
  clusterProperties: {
    sumValue: ["+", ["get", "value"]]
  },
  lineMetrics: true,      // 给 line-gradient 用
  tolerance: 0.375        // 简化容差(默认)
});

三、addLineLayer(不用区分 layout/paint)

map.addLineLayer("my-line", "my-src", {
  lineCap: "round",
  lineJoin: "round",
  lineColor: "#f00",
  lineWidth: 3,
  filter: ["==", ["geometry-type"], "LineString"]
});

四、addFillLayer

map.addFillLayer("my-fill", "my-src", {
  fillColor: "#0af",
  fillOpacity: 0.6,
  fillOutlineColor: "#003",
  filter: ["==", ["geometry-type"], "Polygon"]
});

五、addCircleLayer

map.addCircleLayer("my-circle", "my-src", {
  circleColor: "#f00",
  circleRadius: 5,
  filter: ["==", ["geometry-type"], "Point"]
});

六、addSymbolLayer

map.addSymbolLayer("my-sym", "my-src", {
  iconImage: ["get", "icon"],
  textField: ["get", "name"],
  textSize: 12,
  filter: ["==", ["geometry-type"], "Point"]
});

七、同一 source 三种样式

map.addGeoJSONSource("features", mixedGeoJson);

map.addFillLayer("features-poly", "features", {
  fillColor: "#0af",
  fillOpacity: 0.4,
  filter: ["==", ["geometry-type"], "Polygon"]
});

map.addLineLayer("features-line", "features", {
  lineColor: "#f00",
  lineWidth: 2,
  filter: ["==", ["geometry-type"], "LineString"]
});

map.addCircleLayer("features-pt", "features", {
  circleColor: "#f00",
  circleRadius: 5,
  filter: ["==", ["geometry-type"], "Point"]
});

// 一次更新所有图层
map.getSource("features").setData(newGeoJson);

八、事件 —— 单独建的 layer 用 map.on 而不是 clickLayer

map.on("click", "my-line", e => {
  console.log(e.features[0]);
});

map.on("mouseenter", "my-line", () => map.getCanvas().style.cursor = "pointer");
map.on("mouseleave", "my-line", () => map.getCanvas().style.cursor = "");

九、层序控制

// beforeId 参数决定插入位置
map.addLineLayer("my-line", "my-src", {...}, "other-layer-id");

// 或移动层序
map.moveLayer("my-line", "building-layer");   // 放在 building-layer 下面
map.moveLayer("my-line");                     // 移到最上

十、移除

map.removeLayer("my-line");
map.removeSource("my-src");

// vjmap 扩展:一次移除 layer + 无人使用的 source
map.removeSourceEx("my-src");

十一、何时用封装类 vs 手写

场景 推荐
单图层,快速开发 new vjmap.Polyline / Polygon / Circle 等
同 source 多图层 addGeoJSONSource + add*Layer
复杂表达式调试 addLayer(原生)
框架里批量管理 统一用 addGeoJSONSource 更可控

十二、常见坑

  1. layerId 冲突 → 先 map.getLayer("id") && map.removeLayer("id")。
  2. addSymbolLayer 图标不显示 → 图标名 loadImage 了吗。
  3. 多图层 click 冒泡 → map.on("click", "layerA", ...) 只在该层 hit 时触发;如果要"所有层共用一个 handler",用 map.queryRenderedFeatures(e.point, { layers: [...] })。