阅读过之前的文章基于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: newL.DivIcon({ iconSize: newL.Point(8, 8), className: 'leaflet-div-icon leaflet-editing-icon' }), touchIcon: newL.DivIcon({ iconSize: newL.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 imperialfeet: true, // When not metric, to use feet instead of yards for display.nautic: false, // When not metric, not feet use nautic mile for displayshowLength: true, // Whether to display distance in the tooltipzIndexOffset: 2000, // This should be > than the highest z-index any map layersfactor: 1, // To change distance calculationmaxPoints: 0// Once this number of points are placed, finish shape }, // @method initialize(): voidinitialize: function (map, options) { // if touch, switch to touch iconif (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 optionsif (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) { varlastPtDistance; if (this._markers.length>0) { varfinishMarker; if (this.type===L.Draw.Polyline.TYPE) { finishMarker=this._markers[this._markers.length-1]; } elseif (this.type===L.Draw.Polygon.TYPE) { finishMarker=this._markers[0]; } else { returnInfinity; } varlastMarkerPoint=this._map.latLngToContainerPoint(finishMarker.getLatLng()), potentialMarker=newL.Marker(potentialLatLng, { icon: this.options.icon, zIndexOffset: this.options.zIndexOffset*2 }); varpotentialMarkerPint=this._map.latLngToContainerPoint(potentialMarker.getLatLng()); lastPtDistance=lastMarkerPoint.distanceTo(potentialMarkerPint); } else { lastPtDistance=Infinity; } returnlastPtDistance; } });
上述代码可以从Draw.PolyLine.js中复制而来,只需要将不同的代码修改即可。比如声明不同的类型(必须要,相当于给当前类进行一个类型申明)。
statics: { TYPE: 'polyline4diy' },
// @method initialize(): voidinitialize: function (map, options) { // if touch, switch to touch iconif (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 optionsif (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); },
第二步、绘制激活
functiondrawLine(){ diyDrawLayers.clearLayers(); newL.Draw.Polyline4Diy(map).enable(); }
第三步、自定义对象和默认对象分开定义
// Object created - bind popup to layer, add to feature groupmap.on(L.Draw.Event.CREATED, function(event) { varlayer=event.layer; varlayerType=event.layerType; varcontent=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对象,以及在扩展时需要注意的一些坑,知道如何调试函数并定位问题,最终完成我们的需求