Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

650
Views
Mapbox add popup on hover (layer), close on mouseleave, but keep open on popup hover

I implemented the example just fine:

https://docs.mapbox.com/mapbox-gl-js/example/popup-on-hover/

but I'm struggling to keep the popup open, when hovering the popup (which means leaving the symbol layer) BUT closing the popup when leaving it.

I tried several combinations of event handlers (even a mousemove handler), but since the layer is drawn on canvas, but popup is an domNode I didnt find a solution.

Anyone know where is is implemented, or how to do it?

My Goal is similar behaviour like googla maps on web:

enter image description here

Sample Code from Docs:

// Add a layer showing the places.
map.addLayer({
'id': 'places',
'type': 'circle',
'source': 'places',
'paint': {
'circle-color': '#4264fb',
'circle-radius': 6,
'circle-stroke-width': 2,
'circle-stroke-color': '#ffffff'
}
});
 
// Create a popup, but don't add it to the map yet.
const popup = new mapboxgl.Popup({
closeButton: false,
closeOnClick: false
});
 
map.on('mouseenter', 'places', (e) => {
// Change the cursor style as a UI indicator.
map.getCanvas().style.cursor = 'pointer';
 
// Copy coordinates array.
const coordinates = e.features[0].geometry.coordinates.slice();
const description = e.features[0].properties.description;
 
// Ensure that if the map is zoomed out such that multiple
// copies of the feature are visible, the popup appears
// over the copy being pointed to.
while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360;
}
 
// Populate the popup and set its coordinates
// based on the feature found.
popup.setLngLat(coordinates).setHTML(description).addTo(map);
});
 
map.on('mouseleave', 'places', () => {
map.getCanvas().style.cursor = '';
popup.remove();
});
about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

Recently I have the same problem.

My workaround is to have a function that will close the popup when the userleaves the icon layer or the popup.

If before the timeout is fullfilled the user enters in the popup content, clear the timeout function. (The timeout function will also be called when the user leave popup content).

// TEST modal variables
// popupTEST is the popup where the content will be insert
popupTEST = new mapboxgl.Popup({
    closeButton: false,
    closeOnClick: false,
    className: "popupTEST"
});
// The close of the modal will be via timeout in order to stop removing in when hover the popUp content
popupTESTCloseTimeout = null;

....

this.map.on("mouseenter", "test", (e) => {
    this.map.getCanvas().style.cursor = "pointer";
    // Clear close timeout and delete posible popup
    this.clearPopupTESTCloseTimeout();
    this.popupTEST.remove();
    if (e && e.features && e.features.length > 0 && e.features[0].properties) {
      const popupcontent = document.createElement("div");
      // Create a content using the properties ...
      // Is a react component, but you can use plain javascript
      const Contents = () => (
        <TestModalContent
          properties={properties}
          onMouseEnter={this.clearPopupOACCloseTimeout}
          onMouseLeave={this.closePopupOACWithTimeout} 
        />
      );
      ReactDOM.render(Contents(), popupcontent);
      this.popupTEST.setLngLat([long, lat]).setMaxWidth("none").setDOMContent(popupcontent).addTo(_this.map);
    }        
});

this.map.on("mouseleave", "sit-TEST", () => {
    this.map.getCanvas().style.cursor = "";
    this.closePopupTESTWithTimeout();      
});

closePopupTESTWithTimeout = () => {
    this.popupTESTCloseTimeout = setTimeout(() => this.popupTEST.remove(), 500);
}

clearPopupTESTCloseTimeout = () => {
    if (this.popupTESTCloseTimeout) {
      clearTimeout(this.popupTESTCloseTimeout);
      this.popupTESTCloseTimeout = null;
    }
}
about 4 years ago · Juan Pablo Isaza Report

0

Solution for now:

setting misc. variables on misc. events, then checking in a mousemove handler


const popupDom = document.getElementsByClassName("project-marker-popup");
const popup = new mapboxgl.Popup({
  className: "project-marker-popup",
  maxWidth: "300px",
});
let popUpIsOpen = false;
let mouseOnCircles = false;

// ...

   window.addEventListener(
      "mousemove",
      debounce(250, (e) => {
        const mouseOnPopup = e.target.closest(".project-marker-popup");
        console.log("mouse on popup", mouseOnPopup);
        console.log("popup is open", popUpIsOpen);
        console.log("mouse on circles", mouseOnCircles);

        if (mouseOnPopup || mouseOnCircles) {
          console.log("doing nothing");
          return;
        } else {
          if (popup.remove()) {
            popUpIsOpen = false;
          } else {
            console.error("couldnt close popup");
          }
        }
      })
    );

// ...

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!