OpenLayers Popup – Creating Custom Pop-Up for a GeoJSON Layer in OpenLayers 4

openlayerspopup

I need to get popups showing for just a single feature layer (forest — stored as a GeoJSON) as opposed to all in Openlayers. I currently have the below.

var map = new ol.Map({
    target: "map",
    layers: [
      new ol.layer.Tile({
        source: new ol.source.OSM()
      }),
      new ol.layer.Vector({
        renderMode: 'image',
        style: forestStyle,
        source: new ol.source.Vector({
          url: '../data/forests.geojson',
          format: new ol.format.GeoJSON()
        })
      })
    ]
  });

How do I go about this, please?

PS: I am using Bootstrap 3 and could do with solutions built around it too.

EDIT (After Mike's response)

    {
  "type": "FeatureCollection",
  "features": [
    {
      "type": "Feature",
      "id": 1,
      "geometry": {
        "type": "Polygon",
        "coordinates": [
          [
            [
              22.9629863189914,
              40.8240755346776
            ],
            [
              22.9692602042389,
              40.8166598348136
            ],
            [
              22.9690134736772,
              40.8169316800029
            ],
            [
              22.9687847485475,
              40.81713616158
            ],
            [
              22.9682455495031,
              40.8176072482245
            ],
            [
              22.9679709332253,
              40.81774367484
            ],
            [
              22.9673630702601,
              40.8179212679431
            ],
            [
              22.967084992837,
              40.8182602865605
            ],
            [
              22.9667116917971,
              40.8188278348423
            ],
            [
              22.9664306019971,
              40.8193063705868
            ],
            [
              22.9663027287322,
              40.8196696271834
            ],
            [
              22.9661765887141,
              40.8199428509784
            ],
            [
              22.9648132221368,
              40.8217371937712
            ],
            [
              22.9632330867235,
              40.8238037050033
            ],
            [
              22.9629863189914,
              40.8240755346776
            ]
          ]
        ]
      },
      "properties": {
        "FID": 1,
        "OBJECTID": 119,
        "ID": "GR-4291",
        "Code_12": "131",
        "Remark": " ",
        "Area_ha": 95.6086248776,
        "Shape_Leng": 6533.9468799,
        "code00": 13,
        "Shape_Le_1": 6533.9468799,
        "Shape_Area": 956086.248776,
      }
    }    
  ]
}

`

// Above is the JSON

var forest = new ol.layer.Vector({
    renderMode: 'image',
    style: forestStyle,
    source: new ol.source.Vector({
      url: '../data/forests.geojson',
      format: new ol.format.GeoJSON()
    })
  })

var element = document.getElementById('popup');

  var popup = new ol.Overlay({
    element: element,
    positioning: 'bottom-center',
    stopEvent: false,
    offset: [0, -50]
  });

  map.addOverlay(popup);

  map.on('click', function(evt) {
    var feature = map.forEachFeatureAtPixel(evt.pixel,
      function(feature) {
        return feature;
      },
      { layerFilter: function(candidate) { 
        return (candidate === forest)
      }
    });

    if (feature) {
      var coordinates = feature.getGeometry().getCoordinates();
      console.log(coordinates);
      popup.setPosition(coordinates);
      $(element).popover({
        'placement': 'top',
        'html': true,
        'content': feature.get('id')
      });
      $(element).popover('show');
    } else {
      $(element).popover('destroy');
    }
  });

Best Answer

Similar to the OpenLayer example https://openlayers.org/en/v4.6.5/examples/icon.html

Declare you forest layer separately so it can assigned to a variable, then add it to the map

var forestsLayer = new ol.layer.Vector({
        renderMode: 'image',
        style: forestStyle,
        source: new ol.source.Vector({
          url: '../data/forests.geojson',
          format: new ol.format.GeoJSON()
        })
      });

var map = new ol.Map({
    target: "map",
    layers: [
      new ol.layer.Tile({
        source: new ol.source.OSM()
      }),
      forestsLayer
    ]
  });

If you will be adding other layers and you are only interested in forests you should add a layer filter to the forEachFeatureAtPixel call

var feature = map.forEachFeatureAtPixel(evt.pixel,
            function(feature) {
              return feature;
            },
            { layerFilter: function(candidate) { return (candidate === forestsLayer) } });

Note that the OpenLayers example wasn't written to handle multiple features, even on the same layer, and bootstrap doesn't always work as expected. See https://stackoverflow.com/questions/53947527/popup-with-multiple-points-features

Related Question