You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:59:59