Skip to content

点标记

点标记是地图上最常见的要素类型之一。SDK 提供了简单易用的 API 来添加、管理和样式化点标记。

添加点标记

基础用法

javascript
// 添加一个简单的点标记
const featureId = sdk.addPoint(
  [116.3974, 39.9093], // 坐标 [经度, 纬度]
  { name: "北京" },      // 属性
);

console.log("点标记ID:", featureId);

自定义样式

javascript
// 添加带自定义样式的点标记
const featureId = sdk.addPoint(
  [116.3974, 39.9093],
  { name: "北京", type: "city" },
  {
    paint: {
      "circle-radius": 10,        // 圆圈半径
      "circle-color": "#ff0000",   // 圆圈颜色
      "circle-stroke-width": 2,    // 描边宽度
      "circle-stroke-color": "#ffffff", // 描边颜色
      "circle-opacity": 0.8,       // 透明度
    },
  }
);

使用图标

javascript
// 1. 注册图标
const img = new Image();
img.src = "path/to/icon.png";
img.onload = () => {
  sdk.registerIcon("my-icon", img, {
    pixelRatio: 1,
  });
  
  // 2. 添加使用图标的点标记
  sdk.addSource("marker-source", {
    type: "geojson",
    data: {
      type: "Feature",
      geometry: {
        type: "Point",
        coordinates: [116.3974, 39.9093],
      },
      properties: {
        title: "北京",
      },
    },
  });
  
  // 3. 添加图层
  sdk.addLayer({
    id: "marker-layer",
    source: "marker-source",
    type: "symbol",
    layout: {
      "icon-image": "my-icon",
      "icon-size": 1,
      "text-field": ["get", "title"],
      "text-offset": [0, 1.5],
    },
  });
};

批量添加点标记

使用 GeoJSON 数据

javascript
// 添加多个点标记
const geojson = {
  type: "FeatureCollection",
  features: [
    {
      type: "Feature",
      geometry: {
        type: "Point",
        coordinates: [116.3974, 39.9093],
      },
      properties: { name: "北京" },
    },
    {
      type: "Feature",
      geometry: {
        type: "Point",
        coordinates: [121.4737, 31.2304],
      },
      properties: { name: "上海" },
    },
  ],
};

sdk.addGeoJSON("cities-source", geojson);

// 添加图层
sdk.addLayer({
  id: "cities-layer",
  source: "cities-source",
  type: "circle",
  paint: {
    "circle-radius": 8,
    "circle-color": "#007bff",
  },
});

循环添加

javascript
const cities = [
  { name: "北京", lng: 116.3974, lat: 39.9093 },
  { name: "上海", lng: 121.4737, lat: 31.2304 },
  { name: "广州", lng: 113.2644, lat: 23.1291 },
];

cities.forEach((city) => {
  sdk.addPoint(
    [city.lng, city.lat],
    { name: city.name },
    {
      paint: {
        "circle-radius": 8,
        "circle-color": "#007bff",
      },
    }
  );
});

更新点标记

更新位置

javascript
// 获取要素并更新
const feature = sdk.geoJSONManager.getFeature(featureId);
if (feature) {
  // 更新坐标
  feature.geometry.coordinates = [121.4737, 31.2304];
  
  // 更新源数据
  sdk.getSource("source-id").setData(updatedGeoJSON);
}

更新样式

javascript
// 更新图层样式
sdk.updateLayerStyle("point-layer", {
  paint: {
    "circle-color": "#ff0000",
    "circle-radius": 12,
  },
});

更新属性

javascript
// 更新要素属性
const source = sdk.getSource("source-id");
const data = source._data;

// 找到对应的要素并更新属性
data.features.forEach((feature) => {
  if (feature.id === featureId) {
    feature.properties.name = "新名称";
  }
});

// 更新源数据
source.setData(data);

删除点标记

删除单个点标记

javascript
// 方法1:通过图层ID删除
sdk.removeLayer(featureId);

// 方法2:通过 GeoJSONManager 删除
sdk.geoJSONManager.removeFeature(featureId);

删除多个点标记

javascript
const featureIds = ["feature-1", "feature-2", "feature-3"];

featureIds.forEach((id) => {
  sdk.removeLayer(id);
});

清空所有点标记

javascript
// 删除整个图层
sdk.removeLayer("point-layer");

// 清空源数据
sdk.getSource("source-id").setData({
  type: "FeatureCollection",
  features: [],
});

点标记交互

点击事件

javascript
// 监听点标记点击
sdk.on("click", "point-layer", (e) => {
  const feature = e.features[0];
  console.log("点击的点标记:", feature.properties);
  
  // 显示弹窗
  const popup = new navMap.Popup()
    .setLngLat(e.lngLat)
    .setHTML(`<h3>${feature.properties.name}</h3>`)
    .addTo(sdk.map);
});

悬停效果

javascript
// 鼠标悬停时高亮
sdk.on("mouseenter", "point-layer", (e) => {
  sdk.getCanvas().style.cursor = "pointer";
  
  // 改变样式
  sdk.setPaintProperty("point-layer", "circle-color", "#ff0000");
});

sdk.on("mouseleave", "point-layer", () => {
  sdk.getCanvas().style.cursor = "";
  
  // 恢复样式
  sdk.setPaintProperty("point-layer", "circle-color", "#007bff");
});

使用 ClickManager

javascript
// 使用 ClickManager 简化点击处理
sdk.clickObj.clickPopup(
  "point-layer",
  (feature) => {
    return `<h3>${feature.properties.name}</h3>
            <p>坐标: ${feature.geometry.coordinates.join(", ")}</p>`;
  },
  {
    anchor: "bottom",
    closeButton: true,
  }
);

样式配置

基础样式属性

javascript
sdk.addPoint(
  [116.3974, 39.9093],
  { name: "北京" },
  {
    paint: {
      "circle-radius": 10,              // 半径
      "circle-color": "#ff0000",         // 颜色
      "circle-stroke-width": 2,          // 描边宽度
      "circle-stroke-color": "#ffffff",  // 描边颜色
      "circle-opacity": 1.0,             // 透明度
      "circle-blur": 0,                 // 模糊度
    },
  }
);

动态样式

javascript
// 根据属性值动态设置颜色
sdk.addLayer({
  id: "dynamic-points",
  source: "points-source",
  type: "circle",
  paint: {
    "circle-radius": 8,
    "circle-color": [
      "case",
      ["==", ["get", "type"], "city"],
      "#ff0000",  // 城市:红色
      ["==", ["get", "type"], "airport"],
      "#0000ff",  // 机场:蓝色
      "#00ff00",  // 其他:绿色
    ],
  },
});

根据缩放级别调整大小

javascript
sdk.addLayer({
  id: "zoom-points",
  source: "points-source",
  type: "circle",
  paint: {
    "circle-radius": [
      "interpolate",
      ["linear"],
      ["zoom"],
      5, 5,   // 缩放级别5时半径为5
      10, 10, // 缩放级别10时半径为10
      15, 15, // 缩放级别15时半径为15
    ],
  },
});

聚合显示

对于大量点标记,可以使用聚合功能:

javascript
// 启用聚合
sdk.geoJSONManager.setClusteringEnabled(true);

// 配置聚合参数
sdk.geoJSONManager.setClusteringConfig("points-source", {
  enabled: true,
  radius: 50,      // 聚合半径(像素)
  maxZoom: 16,     // 最大聚合缩放级别
  minPoints: 3,    // 最小聚合点数
});

// 添加聚合图层样式
sdk.addLayer({
  id: "clusters",
  source: "points-source",
  type: "circle",
  filter: ["has", "point_count"],
  paint: {
    "circle-color": [
      "step",
      ["get", "point_count"],
      "#51bbd6",
      100,
      "#f1f075",
      750,
      "#f28cb1",
    ],
    "circle-radius": [
      "step",
      ["get", "point_count"],
      20,
      100,
      30,
      750,
      40,
    ],
  },
});

// 聚合数量标签
sdk.addLayer({
  id: "cluster-count",
  source: "points-source",
  type: "symbol",
  filter: ["has", "point_count"],
  layout: {
    "text-field": "{point_count_abbreviated}",
    "text-font": ["DIN Offc Pro Medium", "Arial Unicode MS Bold"],
    "text-size": 12,
  },
});

完整示例

javascript
let sdk;

async function initMap() {
  sdk = new navMap.MapSDK({
    container: "map",
    center: [116.39, 39.9],
    zoom: 10,
  });

  sdk.on("loadComplete", () => {
    setupPointMarkers();
  });
}

function setupPointMarkers() {
  // 1. 添加单个点标记
  const pointId = sdk.addPoint(
    [116.3974, 39.9093],
    { name: "北京", type: "city" },
    {
      paint: {
        "circle-radius": 10,
        "circle-color": "#ff0000",
        "circle-stroke-width": 2,
        "circle-stroke-color": "#ffffff",
      },
    }
  );

  // 2. 批量添加点标记
  const cities = [
    { name: "北京", lng: 116.3974, lat: 39.9093 },
    { name: "上海", lng: 121.4737, lat: 31.2304 },
    { name: "广州", lng: 113.2644, lat: 23.1291 },
  ];

  cities.forEach((city) => {
    sdk.addPoint(
      [city.lng, city.lat],
      { name: city.name, type: "city" },
      {
        paint: {
          "circle-radius": 8,
          "circle-color": "#007bff",
        },
      }
    );
  });

  // 3. 添加点击事件
  sdk.clickObj.clickPopup(
    pointId,
    (feature) => {
      return `<h3>${feature.properties.name}</h3>
              <p>类型: ${feature.properties.type}</p>`;
    },
    {
      anchor: "bottom",
      closeButton: true,
    }
  );

  // 4. 添加悬停效果
  sdk.on("mouseenter", pointId, () => {
    sdk.setPaintProperty(pointId, "circle-color", "#00ff00");
  });

  sdk.on("mouseleave", pointId, () => {
    sdk.setPaintProperty(pointId, "circle-color", "#ff0000");
  });
}

initMap();

注意事项

  1. 坐标顺序:坐标格式为 [经度, 纬度],注意顺序
  2. 性能优化:大量点标记时考虑使用聚合功能
  3. 样式时机:确保在地图 loadComplete 后再添加点标记
  4. 内存管理:不需要的点标记应及时删除,避免内存泄漏
  5. 图标加载:使用图标时确保图标已加载完成