Mapbox GL JS 等值区域图(Choropleth Map)弹窗异常及居中显示需求咨询
Hey Patrick, no worries at all—first projects with Mapbox GL JS can definitely have little hiccups, let's get this sorted for you!
Why Your Popup Only Appears Occasionally
The main issue with your current code is that you're using e.lngLat (the exact mouse cursor position) to place the popup. For polygon features, Mapbox's hover detection can be inconsistent if your cursor is over thin edges, gaps in the polygon, or if you move your mouse too quickly. This leads to the popup only showing up sometimes.
How to Make Popups Stay Fixed on Feature Centers
To fix this and make the popup always appear at the center of each polygon, we'll use Turf.js—a lightweight library for geospatial calculations that integrates perfectly with Mapbox GL JS. Here's how to adjust your code:
Step 1: Add Turf.js to Your Project
First, you need to include the Turf.js library in your project. You can either download it locally or use a CDN (check the Turf.js official docs for safe, up-to-date ways to add it).
Step 2: Modify Your Hover Event Code
Update the mouseenter event handler to calculate the polygon's center instead of using the mouse position. Here's the revised code with key changes marked:
mapboxgl.accessToken = 'xxx'; const map = new mapboxgl.Map({ container: 'map', style: 'xxx', center: [8.798, 53.122], zoom: 8.15 }); map.on('load', () => { map.addSource('members', { type: 'vector', url: 'xxx' }); map.addLayer({ 'id': 'members_1', 'type': 'fill', 'source': 'members', 'source-layer': 'final_mitgliederV1_1-bcbjyn', 'paint': { 'fill-opacity': 0 } }); // Create a popup, but don't add it to the map yet. const popup = new mapboxgl.Popup({ closeButton: false, closeOnClick: false }); map.on('mouseenter', 'members_1', (e) => { // Change the cursor style as a UI indicator. map.getCanvas().style.cursor = 'pointer'; // Get the hovered feature const feature = e.features[0]; // Calculate the feature's geometric center using Turf.js const centroid = turf.centroid(feature); const centerCoords = centroid.geometry.coordinates; // Build your popup content const members = feature.properties.m_members; const description2 = `<div id='header'><div class='tooltip'>${members}</div>Mitglieder: `; // Set popup to the feature's center instead of mouse position popup.setLngLat(centerCoords).setHTML(description2).addTo(map); }); map.on('mouseleave', 'members_1', () => { map.getCanvas().style.cursor = ''; popup.remove(); }); });
Key Changes Explained
- Turf.js Centroid Calculation:
turf.centroid(feature)takes the polygon feature and returns a point at its geometric center. We then extract this point's coordinates to use for the popup location. - Consistent Popup Placement: By using the feature's center instead of the mouse position, the popup will always appear in the same spot for each polygon, and you won't have issues with inconsistent hover detection causing missing popups.
Bonus Tip for New Mapbox Users
If you want to make your fill layer visible (right now it's transparent with fill-opacity: 0), adjust the paint properties to add a base color and opacity—this will make it clearer which areas are interactive for hover events.
内容的提问来源于stack exchange,提问作者Patrick Pete

