Mapbox GL JS两点测距功能无法停止的技术求助
解决Mapbox GL JS测距按钮无法停止功能的问题
你遇到的核心问题是没有维护测距功能的状态切换逻辑——每次点击按钮都会重复执行初始化代码(添加数据源、图层、绑定点击事件),但完全没有对应的停止机制。下面我给你调整代码,实现点击按钮切换测距启停的完整功能:
关键修改思路
- 新增状态变量
isMeasuring标记当前是否处于测距模式 - 修改
mesure函数,根据状态判断是启动还是停止测距 - 停止时需要移除地图的点击事件监听器、删除对应的图层和数据源,同时清空显示容器
- 给按钮添加文字切换提示,让用户直观了解当前功能状态
修改后的完整代码
// 维护测距状态,初始为未启动 let isMeasuring = false; // 保存地图点击事件的引用,方便后续精准移除 let mapClickHandler = null; var Dist = document.getElementById('tt'); Dist.addEventListener('click', mesure); function mesure() { var distanceContainer = document.getElementById('distance'); if (isMeasuring) { // --- 停止测距逻辑 --- // 移除地图点击事件 if (mapClickHandler) { map.off('click', mapClickHandler); mapClickHandler = null; } // 删除测距相关的图层和数据源 if (map.getLayer('measure-points')) map.removeLayer('measure-points'); if (map.getLayer('measure-lines')) map.removeLayer('measure-lines'); if (map.getSource('geojson')) map.removeSource('geojson'); // 清空测距结果显示 distanceContainer.innerHTML = ''; // 更新状态和按钮文字 isMeasuring = false; Dist.textContent = "启动测距"; return; } // --- 启动测距逻辑 --- isMeasuring = true; Dist.textContent = "停止测距"; // GeoJSON object to hold our measurement features var geojson = { "type": "FeatureCollection", "features": [] }; // Used to draw a line between points var linestring = { "type": "Feature", "geometry": { "type": "LineString", "coordinates": [] } }; map.addSource('geojson', { "type": "geojson", "data": geojson }); // Add styles to the map map.addLayer({ id: 'measure-points', type: 'circle', source: 'geojson', paint: { 'circle-radius': 5, 'circle-color': '#000' }, filter: ['in', '$type', 'Point'] }); map.addLayer({ id: 'measure-lines', type: 'line', source: 'geojson', layout: { 'line-cap': 'round', 'line-join': 'round' }, paint: { 'line-color': '#000', 'line-width': 2.5 }, filter: ['in', '$type', 'LineString'] }); // 将点击事件函数赋值给变量,方便后续移除 mapClickHandler = function (e) { var features = map.queryRenderedFeatures(e.point, { layers: ['measure-points'] }); // Remove the linestring from the group to redraw it if (geojson.features.length > 1) geojson.features.pop(); // Clear the Distance container for new value distanceContainer.innerHTML = ''; // Remove clicked point from map if (features.length) { var id = features[0].properties.id; geojson.features = geojson.features.filter(function (point) { return point.properties.id !== id; }); } else { // Add new point to map var point = { "type": "Feature", "geometry": { "type": "Point", "coordinates": [ e.lngLat.lng, e.lngLat.lat ] }, "properties": { "id": String(new Date().getTime()) } }; geojson.features.push(point); } // Calculate and display distance if there are at least two points if (geojson.features.length > 1) { linestring.geometry.coordinates = geojson.features.map(function (point) { return point.geometry.coordinates; }); geojson.features.push(linestring); var value = document.createElement('pre'); value.textContent = 'Total distance: ' + turf.lineDistance(linestring).toLocaleString() + 'km'; distanceContainer.appendChild(value); } map.getSource('geojson').setData(geojson); }; // 绑定地图点击事件 map.on('click', mapClickHandler); };
代码说明
isMeasuring变量实时跟踪当前功能状态,点击按钮时自动切换启停逻辑mapClickHandler保存了地图点击事件的引用,避免了重复绑定事件或无法精准移除的问题- 停止测距时会彻底清理所有相关资源,避免内存泄漏和界面残留
- 按钮文字随状态切换,提升用户体验
内容的提问来源于stack exchange,提问作者Jean Clement Pdv
相关产品推荐
相关产品推荐

