openlayers-5

Change openlayer popup based on specific feature clicked


My .html:

<div id="map"></div>
<div id="popup" class="ol-popup">
  <a href="#" id="popup-closer" class="ol-popup-closer"></a>
  <div id="popup-content"></div>
</div>

My .js

var attribution = new ol.control.Attribution({
  collapsible: false
});
var map = new ol.Map({
  controls: ol.control.defaults({ attribution: false }).extend([attribution]),
  layers: [
    new ol.layer.Tile({
      source: new ol.source.OSM({
        //url: 'https://tile.openstreetmap.be/osmbe/{z}/{x}/{y}.png'
      })
    })
  ],
  target: 'map',
  view: new ol.View({
    //Center map to producing office address
    center: ol.proj.fromLonLat([-76, 45]),
    zoom: 2.75
  })
});

var CircleStyle = ol.style.Circle
var {Fill, Icon, Stroke, Style} = ol.style;
var styles = {
  'greenCircle': new Style({
    image: new CircleStyle({
      radius: 7,
      stroke: new Stroke({
        color: 'green',
        width: 5,
      }),
    }),
  }),
  'yellowCircle': new Style({
    image: new CircleStyle({
      radius: 7,
      stroke: new Stroke({
        color: 'yellow',
        width: 5,
      }),
    }),
  }),
  'redCircle': new Style({
    image: new CircleStyle({
      radius: 7,
      stroke: new Stroke({
        color: 'red',
        width: 5,
      }),
    }),
  }),
};

var Can = new ol.Feature({
  type: 'greenCircle',
  geometry: new ol.geom.Point(ol.proj.fromLonLat([-79, 44]))
  , id: 1
});
var Ger = new ol.Feature({
  type: 'yellowCircle',
  geometry: new ol.geom.Point(ol.proj.fromLonLat([13, 53]))
  , id: 2
});
var Chn = new ol.Feature({
  type: 'redCircle',
  geometry: new ol.geom.Point(ol.proj.fromLonLat([116, 40]))
  , id: 3
});
var layer = new ol.layer.Vector({
  source: new ol.source.Vector({
    features: [Can, Ger, Chn]
  }),
  style: function (feature) {
    return styles[feature.get('type')];
  }
});
map.addLayer(layer);

var container = document.getElementById('popup');
var content = document.getElementById('popup-content');
var closer = document.getElementById('popup-closer');
var overlay = new ol.Overlay({
  element: container,
  autoPan: true,
  autoPanAnimation: {
    duration: 250
  }
});
map.addOverlay(overlay);

closer.onclick = function () {
  overlay.setPosition(undefined);
  closer.blur();
  return false;
};

map.on('singleclick', function (event) {
  if (map.hasFeatureAtPixel(event.pixel) === true) {
    var coordinate = event.coordinate;
    content.innerHTML = '<b style="color:black;">Canada:</b><br/><a href="program.html#Canada" style="color:blue;">Policy Details</a><br/><a href="service.html" style="color:blue;">Service Details</a>';
    overlay.setPosition(coordinate);
  } else {
    overlay.setPosition(undefined);
    closer.blur();
  }
});

The above code successfully shows three different colored circles on a map and the same popup for each when the user clicks on the circles. The problem is I want to show different popups for each circle when the user clicks on them. I am using Openlayers 5. Appreciate any help. Thanks!


Solution

  • You will need to determine which feature is at the clicked pixel, and display content based on the properties of that feature:

    <!DOCTYPE html>
    <html>
      <head>
        <title>Simple Map</title>
        <link rel="stylesheet" href="https://openlayers.org/en/v5.3.0/css/ol.css" type="text/css">
        <!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
        <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
        <script src="https://openlayers.org/en/v5.3.0/build/ol.js"></script>
        <style>
          .ol-popup {
            position: absolute;
            background-color: white;
            -webkit-filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
            filter: drop-shadow(0 1px 4px rgba(0,0,0,0.2));
            padding: 15px;
            border-radius: 10px;
            border: 1px solid #cccccc;
            bottom: 12px;
            left: -50px;
            min-width: 280px;
          }
          .ol-popup:after, .ol-popup:before {
            top: 100%;
            border: solid transparent;
            content: " ";
            height: 0;
            width: 0;
            position: absolute;
            pointer-events: none;
          }
          .ol-popup:after {
            border-top-color: white;
            border-width: 10px;
            left: 48px;
            margin-left: -10px;
          }
          .ol-popup:before {
            border-top-color: #cccccc;
            border-width: 11px;
            left: 48px;
            margin-left: -11px;
          }
          .ol-popup-closer {
            text-decoration: none;
            position: absolute;
            top: 2px;
            right: 8px;
          }
          .ol-popup-closer:after {
            content: "✖";
          }
        </style>
    
      </head>
      <body>
        <div id="map" class="map"></div>
        <div id="popup" class="ol-popup">
          <a href="#" id="popup-closer" class="ol-popup-closer"></a>
          <div id="popup-content"></div>
        </div>
        <script>
    
    var attribution = new ol.control.Attribution({
      collapsible: false
    });
    var map = new ol.Map({
      controls: ol.control.defaults({ attribution: false }).extend([attribution]),
      layers: [
        new ol.layer.Tile({
          source: new ol.source.OSM({
            //url: 'https://tile.openstreetmap.be/osmbe/{z}/{x}/{y}.png'
          })
        })
      ],
      target: 'map',
      view: new ol.View({
        //Center map to producing office address
        center: ol.proj.fromLonLat([-76, 45]),
        zoom: 2.75
      })
    });
    
    var CircleStyle = ol.style.Circle
    var {Fill, Icon, Stroke, Style} = ol.style;
    var styles = {
      'greenCircle': new Style({
        image: new CircleStyle({
          radius: 7,
          stroke: new Stroke({
            color: 'green',
            width: 5,
          }),
        }),
      }),
      'yellowCircle': new Style({
        image: new CircleStyle({
          radius: 7,
          stroke: new Stroke({
            color: 'yellow',
            width: 5,
          }),
        }),
      }),
      'redCircle': new Style({
        image: new CircleStyle({
          radius: 7,
          stroke: new Stroke({
            color: 'red',
            width: 5,
          }),
        }),
      }),
    };
    
    var Can = new ol.Feature({
      type: 'greenCircle',
      geometry: new ol.geom.Point(ol.proj.fromLonLat([-79, 44]))
      , id: 1
    });
    var Ger = new ol.Feature({
      type: 'yellowCircle',
      geometry: new ol.geom.Point(ol.proj.fromLonLat([13, 53]))
      , id: 2
    });
    var Chn = new ol.Feature({
      type: 'redCircle',
      geometry: new ol.geom.Point(ol.proj.fromLonLat([116, 40]))
      , id: 3
    });
    var layer = new ol.layer.Vector({
      source: new ol.source.Vector({
        features: [Can, Ger, Chn]
      }),
      style: function (feature) {
        return styles[feature.get('type')];
      }
    });
    map.addLayer(layer);
    
    var container = document.getElementById('popup');
    var content = document.getElementById('popup-content');
    var closer = document.getElementById('popup-closer');
    var overlay = new ol.Overlay({
      element: container,
      autoPan: true,
      autoPanAnimation: {
        duration: 250
      }
    });
    map.addOverlay(overlay);
    
    closer.onclick = function () {
      overlay.setPosition(undefined);
      closer.blur();
      return false;
    };
    
    map.on('singleclick', function (event) {
      var feature = map.forEachFeatureAtPixel(event.pixel,
        function(feature) {
          return feature;
        },
        {hitTolerance: 5}
      );
      if (feature) {
        var coordinate = feature.getGeometry().getCoordinates();
        var style = layer.getStyleFunction()(feature);
        content.innerHTML = '<b style="color:' + style.getImage().getStroke().getColor()  + ';background:lightgray;">'  + feature.get('type') + '</b>';
        overlay.setPosition(coordinate);
      } else {
        overlay.setPosition(undefined);
        closer.blur();
      }
    });
    
        </script>
      </body>
    </html>