阅读过之前的文章基于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对象,以及在扩展时需要注意的一些坑,知道如何调试函数并定位问题,最终完成我们的需求