0

I have some problems with popups in OpenLayers, where the popup didn't show up. I'm using Geojson for 2 vector layers, and I want only to show the column "Route, Ramp, and Canopy" for the Bus Stops and "Routes" for the Bus Routes.

I already have this code, but it still didn't show up. What do I have to do with my code now?

// Add a click event listener to the bus routes layer
BusRoutes.on('click', (evt) => {
  // Get the clicked feature
  const feature = map.forEachFeatureAtPixel(evt.pixel, (feature) => feature);
  if (feature) {
    // Get the properties of the feature
    const properties = feature.getProperties();
    // Create the popup content
    const content = createPopupContent(properties);
    // Create the popup overlay
    const popup = new Overlay({
      element: document.createElement('div'),
      autoPan: true,
      autoPanAnimation: {
        duration: 250,
      },
    });
    // Set the content of the popup
    popup.getElement().innerHTML = content;
    // Set the position of the popup
    popup.setPosition(evt.coordinate);
    // Add the popup overlay to the map
    map.addOverlay(popup);
  }
});

// Add a click event listener to the bus stops layer
BusStops.on('click', (evt) => {
  // Get the clicked feature
  const feature = map.forEachFeatureAtPixel(evt.pixel, (feature) => feature);
  if (feature) {
    // Get the properties of the feature
    const properties = feature.getProperties();
    // Create the popup content
    const content = createPopupContent(properties);
    // Create the popup overlay
    const popup = new Overlay({
      element: document.createElement('div'),
      autoPan: true,
      autoPanAnimation: {
        duration: 250,
      },
    });
    // Set the content of the popup
    popup.getElement().innerHTML = content;
    // Set the position of the popup
    popup.setPosition(evt.coordinate);    
    // Add the popup overlay to the map
    map.addOverlay(popup);
  }
});

// Close the popup when the map is clicked
map.on('click', () => {
  map.getOverlays().forEach((overlay) => {
    map.removeOverlay(overlay);
  });
});

UPDATE v.1 I have updated the code but it still doesn't work for me. This is my new code.

// Define a function to create the popup content
function createPopupContent(properties) {
  // Create an array to store the HTML content for the popup
  const content = [];
  // Loop through each property and add it to the content array
  for (const key in properties) {
    if (properties.hasOwnProperty(key)) {
      content.push(`<b>${key}:</b> ${properties[key]}`);
    }
  }
  // Join the content array with line breaks to create the HTML content for the popup
  return content.join('<br>');
}

map.on('click', (evt) => {
  map.getOverlays().getArray().slice().forEach((overlay) => {
    map.removeOverlay(overlay);
  });

  const feature = map.forEachFeatureAtPixel(
    evt.pixel,
    (feature) => feature,
    {layerFilter: (layer) => layer === BusRoutes}
  );
  if (feature){
    // Get the properties of the feature
    const properties = feature.getProperties();
    // Create the popup content
    const content = createPopupContent(properties);
    // Create the popup overlay
    const popup = new Overlay({
      element: document.createElement('div'),
      autoPan: true,
      autoPanAnimation: {
        duration: 250,
      },
    });
  }

  const feature2 = map.forEachFeatureAtPixel(
    evt.pixel,
    (feature) => feature,
    {layerFilter: (layer) => layer === BusStops}
  );
  if (feature2){
    // Get the properties of the feature
    const properties = feature2.getProperties();
    // Create the popup content
    const content = createPopupContent(properties);
    // Create the popup overlay
    const popup = new Overlay({
      element: document.createElement('div'),
      autoPan: true,
      autoPanAnimation: {
        duration: 250,
      },
    });
  }
});

1 Answer 1

1

OpenLayers does not support click events on layers, but you can filter forEachFeatureAtPixel with a layer filter.

I presume you want to clear existing popups before adding new ones, but you should avoid removing items from a live collection or array in a for loop or forEach as the remaining items are moved up the list and you will end up removing every second item. You can use slice to make a static copy of the array.

map.on('click', (evt) => {
  map.getOverlays().getArray().slice().forEach((overlay) => {
    map.removeOverlay(overlay);
  });

  {
    const feature = map.forEachFeatureAtPixel(
      evt.pixel
      (feature) => feature,
      {layerFilter: (layer) => layer === BusRoutes}
    );
    if (feature) {
      // add popup for bus route
    }
  }

  {
    const feature = map.forEachFeatureAtPixel(
      evt.pixel
      (feature) => feature,
      {layerFilter: (layer) => layer === BusStops}
    );
    if (feature) {
      // add popup for bus stop
    }
  }
});
2
  • Thank you for your suggestion. But I have updated the code, but it still doesn't work for me. My new code is in my question up there
    – Deems
    Commented Apr 16, 2023 at 17:36
  • Thank you, it works for me. I forget to add the map.addOverlay() for my popup.
    – Deems
    Commented Apr 16, 2023 at 21:37

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.