Change openlayer popup based on specific feature clicked

24 views Asked by At

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!

1

There are 1 answers

0
Mike On BEST ANSWER

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>