4

I was working on a React project with an OpenLayers map and I was having problems with showing Polygons on the map. When the map is too zoomed out, the Polygons would be to small to see them. So then I tried to display them as pin Icons. By adding a Icon style to the Vector style and only displaying that Vector at a certain zoom level. But I can't get the pin Icons to show on the map.

This is the function where I add the new layer to the map. Note that I have disabled the maxZoom property in the Vector just for testing purposes. So that the Icons should be visible at all zoom levels. But when I get everything working, this would be undone.

import PinIcon from "../../assets/icon.png";

class Map{

...

addUsersPlotBoundriesLayer(newFeatures) {
    if (newFeatures.length > 0) {
      let vectorSource = new VectorSource({
        format: new GeoJSON(),
        minScale: 15000000,
        strategy: bboxStrategy,
      });
      newFeatures.forEach((newFeature) => {
        let feature = new Feature({
          geometry: new Polygon([newFeature.geometry]),
        });
        vectorSource.addFeature(feature);
      });
      let iconStyle = new Style({
        image: new Icon({
          anchor: [0.5, 46],
          anchorXUnits: "fraction",
          anchorYUnits: "pixels",
          src: PinIcon,
        }),
      });
      let vector = new Vector({
        //maxZoom: 13,
        source: vectorSource,
        style: iconStyle,
      });
      vector.setZIndex(10);
      vector.set("name", "plotUserBoundriesLayer");
      this.map.addLayer(vector);
    }
  }

...
}

2 Answers 2

5

Icons are only displayed for Point or MultiPoint geometry. To display Icons for Polygons the style must include a geometry function which returns a Point or MultiPoint (you would usually use the label points)

  let iconStyle = new Style({
    geometry: function(feature) {
      let geometry = feature.getGeometry();
      let geometryType = geometry.getType();
      return (
          geometryType == 'Polygon' ? geometry.getInteriorPoint() :
          geometryType == 'MultiPolygon' ? geometry.getInteriorPoints() :
          geometry
      );
    },
    image: new Icon({
      anchor: [0.5, 46],
      anchorXUnits: "fraction",
      anchorYUnits: "pixels",
      src: PinIcon,
    }),
  });
1
0

Reviving this post as Mike's answer assigns icons to every polygon in a Multipolygon geometry, which wasn't what I hoped for.

To get a single center coordinate of a Multipolygon, this code worked for me:

  let iconStyle = new Style({
    geometry: function(feature) {
        let geometry: Geometry = feature.getGeometry();
        let geometryType: string = geometry.getType();

        if (geometryType == 'MultiPolygon'){
            const multiPoint = geometry.getInteriorPoints();
            const center = getCenter(multiPoint.getExtent());
            multiPoint.setCoordinates([center], "XY");
            return multiPoint;
        } else if (geometryType == 'Polygon'){
            return geometry!.getInteriorPoint();
        } else {
            return geometry;
        }
    },
    image: new Icon({
      anchor: [0.5, 46],
      anchorXUnits: "fraction",
      anchorYUnits: "pixels",
      src: PinIcon,
    }),
  });

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.