Leaflet map locationfound 触发意外的监听器

Leaflet map locationfound triggers unintended listener

我有一张传单地图,其中 map.locate() 可以通过两种方式调用:1. Easybutton 定位按钮,2. 使用 setTimeout 每分钟定期调用。

每个人都有自己的 locationfound 侦听器,或者至少我希望他们有 - 这就是问题所在:单击 easybutton 会同时触发 control._map.on('locationfound'..) easybutton 侦听器和 map.on('locationfound'..) getLocation() 中的侦听器。

对 getLocation() 的常规调用只会触发 map.on('locationfound'..) 侦听器。 这与范围有关吗? 我如何获得它,以便 easybutton 仅触发其预期的侦听器,而对 map.locate() 的 setTimeout 调用仅触发 getLocation() 中的侦听器?

  L.easyButton({
    position: easy_position,
    states:[
      {
        stateName: 'unloaded',
        icon: 'fa-location-arrow',
        title: 'load image',
        onClick: function(control){
          control.state("loading");
          control._map.on('locationfound', function(e){
            alert('location found - easybutton');
            this.setView(e.latlng,18); // go to current location
            control.state('loaded');
            setTimeout(function(){
              control.state('unloaded');
            }, 3000);
          });
          control._map.on('locationerror', function(){
            control.state('error');
            setTimeout(function(){
              control.state('unloaded');
            }, 3000);
          });
          control._map.locate();
          setTimeout(function(){
            control.state('unloaded');
          }, 10000);  // give it ten seconds to find the location
        }
      }, {
        stateName: 'loading',
        icon: 'fa-spinner fa-spin'
      }, {
        stateName: 'loaded',
        icon: 'fa-thumbs-up'
      }, {
        stateName: 'error',
        icon: 'fa-frown-o',
        title: 'location not found'
      }
    ]
  }).addTo(map);

  function updateLocation() {
    getLocation(false);
    setTimeout(updateLocation, 60000);
  }

  getLocation = function(goToLocation) {
    map.on('locationfound', function(e) {
      alert('location found - getLocation()');
      var lat = e.latitude;
      var lng = e.longitude;
      if(goToLocation) {
        pan_to(lat,lng,0.5);
      }
    });
    map.on('locationerror', function(e) {
      console.log(e);
    });
    map.locate({
      setView: false,
      maxZoom: 16
    });
  }

您可以通过使用 map.once() method 附加您的事件侦听器(在您的常规流程和您的按钮中)来缓解您的问题,以便它们在触发一次后被删除:

Behaves as on(…), except the listener will only get fired once and then removed.

仍然存在一些可以同时触发两个侦听器的瞬态情况:如果您的按钮被点击,而您的常规进程已经启动了一个位置,但结果仍然未决,或者相反。

不幸的是,Leaflet 不区分对 map.locate() 方法的调用。因此@IvanSanchez 建议直接使用浏览器 API.

您可以通过在启动一个位置时管理标志/互斥量来消除这些瞬态情况,并且不执行另一个或延迟它,以防您的互斥量被锁定。