Skip to content

线标记

线标记用于在地图上绘制路径、航线、边界等线性要素。SDK 提供了简单易用的 API 来添加和管理线标记。

添加线标记

基础用法

javascript
// 添加一条简单的线
const featureId = sdk.addLine(
  [
    [116.3974, 39.9093], // 起点
    [121.4737, 31.2304], // 终点
  ],
  { name: "北京到上海" }, // 属性
);

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

多段线

javascript
// 添加包含多个点的线
const featureId = sdk.addLine(
  [
    [116.3974, 39.9093],
    [117.2000, 39.1000],
    [118.0000, 38.5000],
    [121.4737, 31.2304],
  ],
  { name: "航线", type: "route" },
);

自定义样式

javascript
// 添加带自定义样式的线
const featureId = sdk.addLine(
  [
    [116.3974, 39.9093],
    [121.4737, 31.2304],
  ],
  { name: "航线" },
  {
    paint: {
      "line-color": "#ff0000",      // 线条颜色
      "line-width": 3,              // 线条宽度
      "line-opacity": 0.8,          // 透明度
      "line-dasharray": [2, 2],     // 虚线样式
      "line-cap": "round",          // 端点样式:round | square | butt
      "line-join": "round",         // 连接点样式:round | bevel | miter
    },
  }
);

批量添加线标记

使用 GeoJSON 数据

javascript
// 添加多条线
const geojson = {
  type: "FeatureCollection",
  features: [
    {
      type: "Feature",
      geometry: {
        type: "LineString",
        coordinates: [
          [116.3974, 39.9093],
          [121.4737, 31.2304],
        ],
      },
      properties: { name: "航线1" },
    },
    {
      type: "Feature",
      geometry: {
        type: "LineString",
        coordinates: [
          [113.2644, 23.1291],
          [120.1551, 30.2741],
        ],
      },
      properties: { name: "航线2" },
    },
  ],
};

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

// 添加图层
sdk.addLayer({
  id: "routes-layer",
  source: "routes-source",
  type: "line",
  paint: {
    "line-color": "#007bff",
    "line-width": 2,
  },
});

循环添加

javascript
const routes = [
  {
    name: "航线1",
    coordinates: [
      [116.3974, 39.9093],
      [121.4737, 31.2304],
    ],
  },
  {
    name: "航线2",
    coordinates: [
      [113.2644, 23.1291],
      [120.1551, 30.2741],
    ],
  },
];

routes.forEach((route) => {
  sdk.addLine(
    route.coordinates,
    { name: route.name },
    {
      paint: {
        "line-color": "#007bff",
        "line-width": 2,
      },
    }
  );
});

更新线标记

更新路径

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

更新样式

javascript
// 更新线条样式
sdk.updateLayerStyle("line-layer", {
  paint: {
    "line-color": "#ff0000",
    "line-width": 5,
  },
});

添加/删除节点

javascript
// 添加节点
function addPointToLine(featureId, newPoint) {
  const feature = sdk.geoJSONManager.getFeature(featureId);
  if (feature && feature.geometry.type === "LineString") {
    feature.geometry.coordinates.push(newPoint);
    sdk.getSource("source-id").setData(updatedGeoJSON);
  }
}

// 删除节点
function removePointFromLine(featureId, pointIndex) {
  const feature = sdk.geoJSONManager.getFeature(featureId);
  if (feature && feature.geometry.type === "LineString") {
    feature.geometry.coordinates.splice(pointIndex, 1);
    sdk.getSource("source-id").setData(updatedGeoJSON);
  }
}

删除线标记

删除单条线

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

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

删除多条线

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

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

清空所有线标记

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

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

线标记交互

点击事件

javascript
// 监听线标记点击
sdk.on("click", "line-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", "line-layer", (e) => {
  sdk.getCanvas().style.cursor = "pointer";
  
  // 改变样式
  sdk.setPaintProperty("line-layer", "line-color", "#ff0000");
  sdk.setPaintProperty("line-layer", "line-width", 5);
});

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

使用 ClickManager

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

样式配置

基础样式属性

javascript
sdk.addLine(
  coordinates,
  { name: "航线" },
  {
    paint: {
      "line-color": "#ff0000",         // 颜色
      "line-width": 3,                 // 宽度
      "line-opacity": 1.0,             // 透明度
      "line-dasharray": [2, 2],        // 虚线样式
      "line-cap": "round",             // 端点样式
      "line-join": "round",            // 连接点样式
      "line-miter-limit": 2,           // 斜接限制
      "line-round-limit": 1.05,        // 圆角限制
      "line-blur": 0,                  // 模糊度
      "line-gradient": null,          // 渐变(需要数据驱动)
      "line-offset": 0,                // 偏移量
      "line-translate": [0, 0],        // 平移
      "line-translate-anchor": "map",  // 平移锚点
    },
  }
);

虚线样式

javascript
// 不同虚线样式
const dashPatterns = {
  solid: [],                    // 实线
  dashed: [2, 2],              // 短虚线
  longDashed: [5, 5],          // 长虚线
  dashDot: [2, 2, 1, 2],       // 点划线
  dot: [1, 1],                 // 点线
};

sdk.addLine(
  coordinates,
  {},
  {
    paint: {
      "line-color": "#ff0000",
      "line-width": 2,
      "line-dasharray": dashPatterns.dashed,
    },
  }
);

动态样式

javascript
// 根据属性值动态设置颜色
sdk.addLayer({
  id: "dynamic-lines",
  source: "lines-source",
  type: "line",
  paint: {
    "line-width": 2,
    "line-color": [
      "case",
      ["==", ["get", "type"], "route"],
      "#ff0000",  // 航线:红色
      ["==", ["get", "type"], "boundary"],
      "#0000ff",  // 边界:蓝色
      "#00ff00",  // 其他:绿色
    ],
  },
});

根据缩放级别调整宽度

javascript
sdk.addLayer({
  id: "zoom-lines",
  source: "lines-source",
  type: "line",
  paint: {
    "line-width": [
      "interpolate",
      ["linear"],
      ["zoom"],
      5, 1,   // 缩放级别5时宽度为1
      10, 2,  // 缩放级别10时宽度为2
      15, 4,  // 缩放级别15时宽度为4
    ],
  },
});

渐变线条

javascript
// 使用数据驱动的渐变
sdk.addLayer({
  id: "gradient-lines",
  source: "lines-source",
  type: "line",
  paint: {
    "line-gradient": [
      "interpolate",
      ["linear"],
      ["line-progress"],
      0,
      "blue",
      0.5,
      "yellow",
      1,
      "red",
    ],
    "line-width": 3,
  },
});

线标记标签

添加沿线标签

javascript
// 添加沿线显示的文本标签
sdk.addLayer({
  id: "line-labels",
  source: "lines-source",
  type: "symbol",
  layout: {
    "symbol-placement": "line",        // 沿线放置
    "text-field": ["get", "name"],     // 文本字段
    "text-font": ["Open Sans Semibold", "Arial Unicode MS Bold"],
    "text-size": 12,
    "text-rotation-alignment": "map",  // 旋转对齐方式
    "text-pitch-alignment": "viewport", // 倾斜对齐方式
  },
  paint: {
    "text-color": "#000000",
    "text-halo-color": "#ffffff",
    "text-halo-width": 2,
  },
});

优化标签显示

SDK 提供了 LineLabelOptimizer 来优化沿线标签的显示:

javascript
// 启用线标签优化
sdk.lineLabelOptimizer.enable();

// 配置优化参数
sdk.lineLabelOptimizer.setOptions({
  minZoom: 10,      // 最小显示缩放级别
  maxZoom: 18,      // 最大显示缩放级别
  spacing: 100,     // 标签间距(像素)
});

完整示例

javascript
let sdk;

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

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

function setupLineMarkers() {
  // 1. 添加单条线
  const lineId = sdk.addLine(
    [
      [116.3974, 39.9093],
      [121.4737, 31.2304],
    ],
    { name: "北京到上海", type: "route" },
    {
      paint: {
        "line-color": "#ff0000",
        "line-width": 3,
        "line-opacity": 0.8,
        "line-dasharray": [2, 2],
      },
    }
  );

  // 2. 批量添加线
  const routes = [
    {
      name: "航线1",
      coordinates: [
        [116.3974, 39.9093],
        [121.4737, 31.2304],
      ],
    },
    {
      name: "航线2",
      coordinates: [
        [113.2644, 23.1291],
        [120.1551, 30.2741],
      ],
    },
  ];

  routes.forEach((route) => {
    sdk.addLine(
      route.coordinates,
      { name: route.name, type: "route" },
      {
        paint: {
          "line-color": "#007bff",
          "line-width": 2,
        },
      }
    );
  });

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

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

  sdk.on("mouseleave", lineId, () => {
    sdk.setPaintProperty(lineId, "line-color", "#ff0000");
    sdk.setPaintProperty(lineId, "line-width", 3);
  });
}

initMap();

注意事项

  1. 坐标顺序:坐标格式为 [经度, 纬度],注意顺序
  2. 最少点数:线至少需要2个点
  3. 性能优化:大量线标记时考虑使用 LOD 配置
  4. 样式时机:确保在地图 loadComplete 后再添加线标记
  5. 标签优化:使用 LineLabelOptimizer 可以提升大量标签的性能