Implementé el ejemplo muy bien:
https://docs.mapbox.com/mapbox-gl-js/example/popup-on-hover/
pero estoy luchando por mantener la ventana emergente abierta, cuando desplazo la ventana emergente (lo que significa dejar la capa de símbolo) PERO cierro la ventana emergente cuando la dejo.
Probé varias combinaciones de controladores de eventos (incluso un controlador de movimiento del mouse), pero dado que la capa se dibuja en el lienzo, pero la ventana emergente es un domNode, no encontré una solución.
¿Alguien sabe dónde está implementado, o cómo hacerlo?
Mi objetivo es un comportamiento similar al de Google Maps en la web:
Código de muestra de 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(); });Recientemente tengo el mismo problema.
Mi solución es tener una función que cierre la ventana emergente cuando el usuario deje la capa de iconos o la ventana emergente.
Si antes de que se complete el tiempo de espera, el usuario ingresa el contenido emergente, borre la función de tiempo de espera. (La función de tiempo de espera también se llamará cuando el usuario deje el contenido emergente).
// 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; } }Solución por ahora:
configuración miscelánea variables en misc. eventos, luego registrando un controlador de movimiento del mouse
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"); } } }) ); // ...