Skip to content

Polygon Marker

Polygon markers are used to draw areas, polygons, and other areal features on the map. The SDK provides simple and easy-to-use APIs to add and manage polygon markers.

Adding Polygon Markers

Basic Usage

javascript
// Add a simple polygon
const featureId = sdk.addPolygon(
  [
    [
      [116.3974, 39.9093], // First point
      [121.4737, 39.9093], // Second point
      [121.4737, 31.2304], // Third point
      [116.3974, 31.2304], // Fourth point
      [116.3974, 39.9093], // Close polygon (return to start)
    ],
  ],
  { name: "Area" }, // Properties
);

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

Polygon with Holes

javascript
// Add a polygon with holes (outer ring + inner ring)
const featureId = sdk.addPolygon(
  [
    // Outer ring
    [
      [116.3974, 39.9093],
      [121.4737, 39.9093],
      [121.4737, 31.2304],
      [116.3974, 31.2304],
      [116.3974, 39.9093],
    ],
    // Inner ring (hole)
    [
      [118.0, 36.0],
      [119.0, 36.0],
      [119.0, 35.0],
      [118.0, 35.0],
      [118.0, 36.0],
    ],
  ],
  { name: "Area with hole" },
);

Custom Styles

javascript
// Add a polygon with custom styles
const featureId = sdk.addPolygon(
  [
    [
      [116.3974, 39.9093],
      [121.4737, 39.9093],
      [121.4737, 31.2304],
      [116.3974, 31.2304],
      [116.3974, 39.9093],
    ],
  ],
  { name: "Area", type: "area" },
  {
    paint: {
      "fill-color": "#ff0000",        // Fill color
      "fill-opacity": 0.5,            // Fill opacity
      "fill-outline-color": "#000000", // Outline color
      "fill-pattern": null,           // Fill pattern (requires sprite)
    },
  }
);

Batch Adding Polygon Markers

Using GeoJSON Data

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

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

// Add layer
sdk.addLayer({
  id: "areas-layer",
  source: "areas-source",
  type: "fill",
  paint: {
    "fill-color": "#007bff",
    "fill-opacity": 0.5,
  },
});

Loop Adding

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

areas.forEach((area) => {
  sdk.addPolygon(
    area.coordinates,
    { name: area.name },
    {
      paint: {
        "fill-color": "#007bff",
        "fill-opacity": 0.5,
      },
    }
  );
});

Updating Polygon Markers

Update Shape

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

Update Style

javascript
// Update polygon style
sdk.updateLayerStyle("polygon-layer", {
  paint: {
    "fill-color": "#ff0000",
    "fill-opacity": 0.8,
  },
});

Add/Remove Vertices

javascript
// Add vertex
function addVertexToPolygon(featureId, ringIndex, newVertex) {
  const feature = sdk.geoJSONManager.getFeature(featureId);
  if (feature && feature.geometry.type === "Polygon") {
    const ring = feature.geometry.coordinates[ringIndex];
    // Insert at second-to-last position (maintain closure)
    ring.splice(-1, 0, newVertex);
    sdk.getSource("source-id").setData(updatedGeoJSON);
  }
}

// Remove vertex
function removeVertexFromPolygon(featureId, ringIndex, vertexIndex) {
  const feature = sdk.geoJSONManager.getFeature(featureId);
  if (feature && feature.geometry.type === "Polygon") {
    const ring = feature.geometry.coordinates[ringIndex];
    // Cannot remove last point (closure point)
    if (ring.length > 4 && vertexIndex < ring.length - 1) {
      ring.splice(vertexIndex, 1);
      sdk.getSource("source-id").setData(updatedGeoJSON);
    }
  }
}

Deleting Polygon Markers

Delete Single Polygon

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

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

Delete Multiple Polygons

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

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

Clear All Polygon Markers

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

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

Polygon Marker Interactions

Click Event

javascript
// Listen to polygon marker click
sdk.on("click", "polygon-layer", (e) => {
  const feature = e.features[0];
  console.log("Clicked polygon:", 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", "polygon-layer", (e) => {
  sdk.getCanvas().style.cursor = "pointer";
  
  // Change style
  sdk.setPaintProperty("polygon-layer", "fill-color", "#ff0000");
  sdk.setPaintProperty("polygon-layer", "fill-opacity", 0.8);
});

sdk.on("mouseleave", "polygon-layer", () => {
  sdk.getCanvas().style.cursor = "";
  
  // Restore style
  sdk.setPaintProperty("polygon-layer", "fill-color", "#007bff");
  sdk.setPaintProperty("polygon-layer", "fill-opacity", 0.5);
});

Using ClickManager

javascript
// Use ClickManager to simplify click handling
sdk.clickObj.clickPopup(
  "polygon-layer",
  (feature) => {
    const area = calculateArea(feature.geometry.coordinates);
    return `<h3>${feature.properties.name}</h3>
            <p>Area: ${area.toFixed(2)} km²</p>`;
  },
  {
    anchor: "bottom",
    closeButton: true,
  }
);

Style Configuration

Basic Style Properties

javascript
sdk.addPolygon(
  coordinates,
  { name: "Area" },
  {
    paint: {
      "fill-color": "#ff0000",         // Fill color
      "fill-opacity": 0.5,               // Fill opacity
      "fill-outline-color": "#000000",  // Outline color
      "fill-pattern": null,             // Fill pattern
      "fill-translate": [0, 0],         // Translate
      "fill-translate-anchor": "map",   // Translate anchor
    },
  }
);

Outline Style

javascript
// Add outline layer
sdk.addLayer({
  id: "polygon-outline",
  source: "polygon-source",
  type: "line",
  paint: {
    "line-color": "#000000",
    "line-width": 2,
    "line-opacity": 1.0,
    "line-dasharray": [2, 2], // Dashed outline
  },
});

Dynamic Styles

javascript
// Dynamically set color based on property value
sdk.addLayer({
  id: "dynamic-polygons",
  source: "polygons-source",
  type: "fill",
  paint: {
    "fill-opacity": 0.5,
    "fill-color": [
      "case",
      ["==", ["get", "type"], "restricted"],
      "#ff0000",  // Restricted area: red
      ["==", ["get", "type"], "controlled"],
      "#0000ff",  // Controlled area: blue
      "#00ff00",  // Other: green
    ],
  },
});

Adjust Opacity Based on Zoom Level

javascript
sdk.addLayer({
  id: "zoom-polygons",
  source: "polygons-source",
  type: "fill",
  paint: {
    "fill-color": "#007bff",
    "fill-opacity": [
      "interpolate",
      ["linear"],
      ["zoom"],
      5, 0.2,  // Opacity 0.2 at zoom level 5
      10, 0.5, // Opacity 0.5 at zoom level 10
      15, 0.8, // Opacity 0.8 at zoom level 15
    ],
  },
});

Fill Pattern

javascript
// Use fill pattern (requires sprite loading first)
sdk.addLayer({
  id: "pattern-polygons",
  source: "polygons-source",
  type: "fill",
  paint: {
    "fill-pattern": "pattern-name", // Pattern name in sprite
    "fill-opacity": 0.8,
  },
});

Geometry Calculations

Calculate Area

javascript
function calculateArea(coordinates) {
  // Use turf.js or other geometry calculation library
  const polygon = turf.polygon(coordinates);
  return turf.area(polygon); // Returns square meters
}

// Usage example
sdk.on("click", "polygon-layer", (e) => {
  const feature = e.features[0];
  const area = calculateArea(feature.geometry.coordinates);
  console.log("Area:", area, "square meters");
});

Calculate Centroid

javascript
function getCentroid(coordinates) {
  const polygon = turf.polygon(coordinates);
  const centroid = turf.centroid(polygon);
  return centroid.geometry.coordinates;
}

// Usage example
const center = getCentroid(polygonCoordinates);
sdk.flyTo({
  center: center,
  zoom: 12,
});

Check if Point is Inside Polygon

javascript
function pointInPolygon(point, polygonCoordinates) {
  const pt = turf.point(point);
  const polygon = turf.polygon(polygonCoordinates);
  return turf.booleanPointInPolygon(pt, polygon);
}

// Usage example
const isInside = pointInPolygon([116.3974, 39.9093], polygonCoordinates);
console.log("Point is inside polygon:", isInside);

Complete Example

javascript
let sdk;

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

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

function setupPolygonMarkers() {
  // 1. Add single polygon
  const polygonId = sdk.addPolygon(
    [
      [
        [116.3974, 39.9093],
        [121.4737, 39.9093],
        [121.4737, 31.2304],
        [116.3974, 31.2304],
        [116.3974, 39.9093],
      ],
    ],
    { name: "Area", type: "area" },
    {
      paint: {
        "fill-color": "#ff0000",
        "fill-opacity": 0.5,
        "fill-outline-color": "#000000",
      },
    }
  );

  // 2. Add outline
  sdk.addLayer({
    id: `${polygonId}-outline`,
    source: polygonId,
    type: "line",
    paint: {
      "line-color": "#000000",
      "line-width": 2,
    },
  });

  // 3. Batch add polygons
  const areas = [
    {
      name: "Area 1",
      coordinates: [
        [
          [116.3974, 39.9093],
          [121.4737, 39.9093],
          [121.4737, 31.2304],
          [116.3974, 31.2304],
          [116.3974, 39.9093],
        ],
      ],
    },
  ];

  areas.forEach((area) => {
    sdk.addPolygon(
      area.coordinates,
      { name: area.name, type: "area" },
      {
        paint: {
          "fill-color": "#007bff",
          "fill-opacity": 0.5,
        },
      }
    );
  });

  // 4. Add click event
  sdk.clickObj.clickPopup(
    polygonId,
    (feature) => {
      const area = calculateArea(feature.geometry.coordinates);
      return `<h3>${feature.properties.name}</h3>
              <p>Type: ${feature.properties.type}</p>
              <p>Area: ${(area / 1000000).toFixed(2)} km²</p>`;
    },
    {
      anchor: "bottom",
      closeButton: true,
    }
  );

  // 5. Add hover effect
  sdk.on("mouseenter", polygonId, () => {
    sdk.setPaintProperty(polygonId, "fill-color", "#00ff00");
    sdk.setPaintProperty(polygonId, "fill-opacity", 0.8);
  });

  sdk.on("mouseleave", polygonId, () => {
    sdk.setPaintProperty(polygonId, "fill-color", "#ff0000");
    sdk.setPaintProperty(polygonId, "fill-opacity", 0.5);
  });
}

initMap();

Notes

  1. Coordinate Order: Coordinate format is [longitude, latitude], pay attention to the order
  2. Closed Polygon: The first and last points of a polygon must be the same
  3. Ring Direction: Outer ring counterclockwise, inner ring (hole) clockwise
  4. Performance Optimization: Consider using LOD configuration for large numbers of polygon markers
  5. Style Timing: Ensure polygon markers are added after map loadComplete
  6. Geometry Calculations: Complex geometry calculations recommend using professional libraries like turf.js