解决Leaflet.draw中polyline绘制无法结束的问题

53 篇文章 18 订阅
41 篇文章 6 订阅

        阅读过之前的文章基于Leaflet.draw的gis图形标绘实战干货!基于Leaflet.draw的自定义绘制,也许你大致知道了如何扩展自己的基本绘制以及在无draw按钮的情况下激活绘制组件。但是你有没有自己扩展过polyline,比如需要额外增加一个数据编辑图层,用于保存一条线或者一个面。那此时我们该怎么做呢?

        解决思路如下:

        1、扩展polyline对象。

        2、扩展map的创建函数,将draw组件注册的对象类型和自定义对象的type分开,并可以单独处理。

        3、针对需求创建自定义处理函数。

        第一步、创建扩展对象类,在Draw.Polyline.js平级目录下新增Draw.Diy.js类,代码如下:

/**
 * @class L.Draw.Polyline4Diy
 * @aka Draw.Polyline4Diy
 * @inherits L.Draw.Polyline
 */
L.Draw.Polyline4Diy = L.Draw.Polyline.extend({
  statics: {
    TYPE: 'polyline4diy'
  },
​
  options: {
    allowIntersection: true,
    repeatMode: false,
    drawError: {
      color: '#b00b00',
      timeout: 2500
    },
    icon: new L.DivIcon({
      iconSize: new L.Point(8, 8),
      className: 'leaflet-div-icon leaflet-editing-icon'
    }),
    touchIcon: new L.DivIcon({
      iconSize: new L.Point(20, 20),
      className: 'leaflet-div-icon leaflet-editing-icon leaflet-touch-icon'
    }),
    guidelineDistance: 20,
    maxGuideLineLength: 4000,
    shapeOptions: {
      stroke: true,
      color: '#3388ff',
      weight: 4,
      opacity: 0.5,
      fill: false,
      clickable: true
    },
    metric: true, // Whether to use the metric measurement system or imperial
    feet: true, // When not metric, to use feet instead of yards for display.
    nautic: false, // When not metric, not feet use nautic mile for display
    showLength: true, // Whether to display distance in the tooltip
    zIndexOffset: 2000, // This should be > than the highest z-index any map layers
    factor: 1, // To change distance calculation
    maxPoints: 0 // Once this number of points are placed, finish shape
  },
​
  // @method initialize(): void
  initialize: function (map, options) {
    // if touch, switch to touch icon
    if (L.Browser.touch) {
      this.options.icon = this.options.touchIcon;
    }
​
    // Need to set this here to ensure the correct message is used.
    this.options.drawError.message = L.drawLocal.draw.handlers.polyline.error;
​
    // Merge default drawError options with custom options
    if (options && options.drawError) {
      options.drawError = L.Util.extend({}, this.options.drawError, options.drawError);
    }
​
    // Save the type so super can fire, need to do this as cannot do this.TYPE :(
    this.type = L.Draw.Polyline4Diy.TYPE;
​
    L.Draw.Feature.prototype.initialize.call(this, map, options);
  },
​
  // calculate if we are currently within close enough distance
  // of the closing point (first point for shapes, last point for lines)
  // this is semi-ugly code but the only reliable way i found to get the job done
  // note: calculating point.distanceTo between mouseDownOrigin and last marker did NOT work
  _calculateFinishDistance: function (potentialLatLng) {
    var lastPtDistance;
    if (this._markers.length > 0) {
      var finishMarker;
      if (this.type === L.Draw.Polyline.TYPE) {
        finishMarker = this._markers[this._markers.length - 1];
      } else if (this.type === L.Draw.Polygon.TYPE) {
        finishMarker = this._markers[0];
      } else {
        return Infinity;
      }
      var lastMarkerPoint = this._map.latLngToContainerPoint(finishMarker.getLatLng()),
        potentialMarker = new L.Marker(potentialLatLng, {
          icon: this.options.icon,
          zIndexOffset: this.options.zIndexOffset * 2
        });
      var potentialMarkerPint = this._map.latLngToContainerPoint(potentialMarker.getLatLng());
      lastPtDistance = lastMarkerPoint.distanceTo(potentialMarkerPint);
    } else {
      lastPtDistance = Infinity;
    }
    return lastPtDistance;
  }
  
});

        上述代码可以从Draw.PolyLine.js中复制而来,只需要将不同的代码修改即可。比如声明不同的类型(必须要,相当于给当前类进行一个类型申明)。

statics: {
    TYPE: 'polyline4diy'
  },
// @method initialize(): void
  initialize: function (map, options) {
    // if touch, switch to touch icon
    if (L.Browser.touch) {
      this.options.icon = this.options.touchIcon;
    }
​
    // Need to set this here to ensure the correct message is used.
    this.options.drawError.message = L.drawLocal.draw.handlers.polyline.error;
​
    // Merge default drawError options with custom options
    if (options && options.drawError) {
      options.drawError = L.Util.extend({}, this.options.drawError, options.drawError);
    }
​
    // Save the type so super can fire, need to do this as cannot do this.TYPE :(
    this.type = L.Draw.Polyline4Diy.TYPE;
​
    L.Draw.Feature.prototype.initialize.call(this, map, options);
  },

        第二步、绘制激活

function drawLine(){
    diyDrawLayers.clearLayers();
    new L.Draw.Polyline4Diy(map).enable();
}

        第三步、自定义对象和默认对象分开定义

// Object created - bind popup to layer, add to feature group
 map.on(L.Draw.Event.CREATED, function(event) {
      var layer = event.layer;
      var layerType = event.layerType;
      var content = getPopupContent(layer);
      if (content !== null) {
          layer.bindPopup(content);
      }
      if(layerType == L.Draw.Rectangle4Diy.TYPE || layerType == L.Draw.Polyline4Diy.TYPE){
        diyDrawLayers.addLayer(layer);
      }else{
        drawnItems.addLayer(layer);
      }
  });

        通过以上步骤可完成自定义polyline扩展,功能如下图:

        实际操作时,你会发现,当点击最后一个绘制的点,绘制动作并未停下,而polyline绘制时却可以停下。是哪里出现了问题呢?

        在Draw.Diy.js文件中,我们去查找绘制结束的计算方法,并debug看下发生了什么?

        debug发现,其lastPtDistance是INfinity,继续往前看,

        仔细观察发现,我们在计算时,忘记了将type修改成为我们自己定义的类型,因此会导致计算失误,无法绘制结束,只需要将type修改为如下即可

if (this.type === L.Draw.Polyline4Diy.TYPE)

        清空缓存,在此进行绘制就会发现,点击线的最后一个点可以正常结束。

        总结:通过本文,可以了解如何自定义Draw.PolyLine对象,以及在扩展时需要注意的一些坑,知道如何调试函数并定位问题,最终完成我们的需求

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜郎king

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值