Skip to content

Line Marker

Line markers are used to draw paths, routes, boundaries, and other linear features on the map. The SDK provides simple and easy-to-use APIs to add and manage line markers.

Adding Line Markers

Basic Usage

javascript
// Add a simple line
const featureId = sdk.addLine(
  [
    [116.3974, 39.9093], // Start point
    [121.4737, 31.2304], // End point
  ],
  { name: "Beijing to Shanghai" }, // Properties
);

console.log("Line marker ID:", featureId);

Multi-segment Line

javascript
// Add a line with multiple points
const featureId = sdk.addLine(
  [
    [116.3974, 39.9093],
    [117.2000, 39.1000],
    [118.0000, 38.5000],
    [121.4737, 31.2304],
  ],
  { name: "Route", type: "route" },
);

Custom Styles

javascript
// Add a line with custom styles
const featureId = sdk.addLine(
  [
    [116.3974, 39.9093],
    [121.4737, 31.2304],
  ],
  { name: "Route" },
  {
    paint: {
      "line-color": "#ff0000",      // Line color
      "line-width": 3,              // Line width
      "line-opacity": 0.8,          // Opacity
      "line-dasharray": [2, 2],     // Dash pattern
      "line-cap": "round",          // End cap style: round | square | butt
      "line-join": "round",         // Join style: round | bevel | miter
    },
  }
);

Batch Adding Line Markers

Using GeoJSON Data

javascript
// Add multiple lines
const geojson = {
  type: "FeatureCollection",
  features: [
    {
      type: "Feature",
      geometry: {
        type: "LineString",
        coordinates: [
          [116.3974, 39.9093],
          [121.4737, 31.2304],
        ],
      },
      properties: { name: "Route 1" },
    },
    {
      type: "Feature",
      geometry: {
        type: "LineString",
        coordinates: [
          [113.2644, 23.1291],
          [120.1551, 30.2741],
        ],
      },
      properties: { name: "Route 2" },
    },
  ],
};

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

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

Loop Adding

javascript
const routes = [
  {
    name: "Route 1",
    coordinates: [
      [116.3974, 39.9093],
      [121.4737, 31.2304],
    ],
  },
  {
    name: "Route 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,
      },
    }
  );
});

Updating Line Markers

Update Path

javascript
// Get feature and update coordinates
const feature = sdk.geoJSONManager.getFeature(featureId);
if (feature) {
  // Update coordinates
  feature.geometry.coordinates = [
    [116.3974, 39.9093],
    [117.0000, 39.0000],
    [121.4737, 31.2304],
  ];
  
  // Update source data
  sdk.getSource("source-id").setData(updatedGeoJSON);
}

Update Style

javascript
// Update line style
sdk.updateLayerStyle("line-layer", {
  paint: {
    "line-color": "#ff0000",
    "line-width": 5,
  },
});

Add/Remove Points

javascript
// Add point
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);
  }
}

// Remove point
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);
  }
}

Deleting Line Markers

Delete Single Line

javascript
// Method 1: Delete by layer ID
sdk.removeLayer(featureId);

// Method 2: Delete via GeoJSONManager
sdk.geoJSONManager.removeFeature(featureId);

Delete Multiple Lines

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

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

Clear All Line Markers

javascript
// Delete entire layer
sdk.removeLayer("line-layer");

// Clear source data
sdk.getSource("source-id").setData({
  type: "FeatureCollection",
  features: [],
});

Line Marker Interactions

Click Event

javascript
// Listen to line marker click
sdk.on("click", "line-layer", (e) => {
  const feature = e.features[0];
  console.log("Clicked line:", feature.properties);
  
  // Show popup
  const popup = new navMap.Popup()
    .setLngLat(e.lngLat)
    .setHTML(`<h3>${feature.properties.name}</h3>`)
    .addTo(sdk.map);
});

Hover Effect

javascript
// Highlight on mouse hover
sdk.on("mouseenter", "line-layer", (e) => {
  sdk.getCanvas().style.cursor = "pointer";
  
  // Change style
  sdk.setPaintProperty("line-layer", "line-color", "#ff0000");
  sdk.setPaintProperty("line-layer", "line-width", 5);
});

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

Using ClickManager

javascript
// Use ClickManager to simplify click handling
sdk.clickObj.clickPopup(
  "line-layer",
  (feature) => {
    return `<h3>${feature.properties.name}</h3>
            <p>Length: ${calculateLength(feature.geometry.coordinates)} km</p>`;
  },
  {
    anchor: "bottom",
    closeButton: true,
  }
);

Style Configuration

Basic Style Properties

javascript
sdk.addLine(
  coordinates,
  { name: "Route" },
  {
    paint: {
      "line-color": "#ff0000",         // Color
      "line-width": 3,                 // Width
      "line-opacity": 1.0,             // Opacity
      "line-dasharray": [2, 2],        // Dash pattern
      "line-cap": "round",             // End cap style
      "line-join": "round",            // Join style
      "line-miter-limit": 2,           // Miter limit
      "line-round-limit": 1.05,        // Round limit
      "line-blur": 0,                  // Blur
      "line-gradient": null,          // Gradient (requires data-driven)
      "line-offset": 0,                // Offset
      "line-translate": [0, 0],        // Translate
      "line-translate-anchor": "map",  // Translate anchor
    },
  }
);

Dash Patterns

javascript
// Different dash patterns
const dashPatterns = {
  solid: [],                    // Solid line
  dashed: [2, 2],              // Short dash
  longDashed: [5, 5],          // Long dash
  dashDot: [2, 2, 1, 2],       // Dash-dot
  dot: [1, 1],                 // Dotted
};

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

Dynamic Styles

javascript
// Dynamically set color based on property value
sdk.addLayer({
  id: "dynamic-lines",
  source: "lines-source",
  type: "line",
  paint: {
    "line-width": 2,
    "line-color": [
      "case",
      ["==", ["get", "type"], "route"],
      "#ff0000",  // Route: red
      ["==", ["get", "type"], "boundary"],
      "#0000ff",  // Boundary: blue
      "#00ff00",  // Other: green
    ],
  },
});

Adjust Width Based on Zoom Level

javascript
sdk.addLayer({
  id: "zoom-lines",
  source: "lines-source",
  type: "line",
  paint: {
    "line-width": [
      "interpolate",
      ["linear"],
      ["zoom"],
      5, 1,   // Width 1 at zoom level 5
      10, 2,  // Width 2 at zoom level 10
      15, 4,  // Width 4 at zoom level 15
    ],
  },
});

Gradient Lines

javascript
// Use data-driven gradient
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,
  },
});

Line Marker Labels

Add Line Labels

javascript
// Add text labels displayed along lines
sdk.addLayer({
  id: "line-labels",
  source: "lines-source",
  type: "symbol",
  layout: {
    "symbol-placement": "line",        // Place along line
    "text-field": ["get", "name"],     // Text field
    "text-font": ["Open Sans Semibold", "Arial Unicode MS Bold"],
    "text-size": 12,
    "text-rotation-alignment": "map",  // Rotation alignment
    "text-pitch-alignment": "viewport", // Pitch alignment
  },
  paint: {
    "text-color": "#000000",
    "text-halo-color": "#ffffff",
    "text-halo-width": 2,
  },
});

Optimize Label Display

The SDK provides LineLabelOptimizer to optimize line label display:

javascript
// Enable line label optimization
sdk.lineLabelOptimizer.enable();

// Configure optimization parameters
sdk.lineLabelOptimizer.setOptions({
  minZoom: 10,      // Minimum display zoom level
  maxZoom: 18,      // Maximum display zoom level
  spacing: 100,     // Label spacing (pixels)
});

Complete Example

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. Add single line
  const lineId = sdk.addLine(
    [
      [116.3974, 39.9093],
      [121.4737, 31.2304],
    ],
    { name: "Beijing to Shanghai", type: "route" },
    {
      paint: {
        "line-color": "#ff0000",
        "line-width": 3,
        "line-opacity": 0.8,
        "line-dasharray": [2, 2],
      },
    }
  );

  // 2. Batch add lines
  const routes = [
    {
      name: "Route 1",
      coordinates: [
        [116.3974, 39.9093],
        [121.4737, 31.2304],
      ],
    },
    {
      name: "Route 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. Add click event
  sdk.clickObj.clickPopup(
    lineId,
    (feature) => {
      return `<h3>${feature.properties.name}</h3>
              <p>Type: ${feature.properties.type}</p>`;
    },
    {
      anchor: "bottom",
      closeButton: true,
    }
  );

  // 4. Add hover effect
  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();

Notes

  1. Coordinate Order: Coordinate format is [longitude, latitude], pay attention to the order
  2. Minimum Points: A line requires at least 2 points
  3. Performance Optimization: Consider using LOD configuration for large numbers of line markers
  4. Style Timing: Ensure line markers are added after map loadComplete
  5. Label Optimization: Using LineLabelOptimizer can improve performance for large numbers of labels