L.Control.Draw = L.Control.extend({
//是否初始化
_initialized: false,
//统计
_lC: 0,
//测量对象集合
_measureObjs: {},
//是否完成当前测绘
_finished: true,
//新测量
isNewElevation: true,
moveMarker: false,
//测量参数
options: {
position: 'topright',
autoZIndex: true,
offset: [10, 10],
background: "#000",
color: "#fff",
size: 14,
closeButton: true,
iconUrl:'./images/marker-icon.png'
},
initialize: function(options) {
L.setOptions(this, options);
return this;
},
onAdd: function(map) {
this._map = map;
this._createControl();
switch (this.options.position) {
case 'topleft':
this._container.style.marginLeft = this.options.offset[0] + 'px';
this._container.style.marginTop = this.options.offset[1] + 'px';
break;
case 'topright':
this._container.style.marginRight = this.options.offset[0] + 'px';
this._container.style.marginTop = this.options.offset[1] + 'px';
break;
case 'bottomleft':
this._container.style.marginLeft = this.options.offset[0] + 'px';
this._container.style.marginBottom = this.options.offset[1] + 'px';
break;
case 'bottomright':
this._container.style.marginRight = this.options.offset[0] + 'px';
this._container.style.marginBottom = this.options.offset[1] + 'px';
break;
}
return this._container;
},
_createControl: function() {
var _this = this;
this._container = L.DomUtil.create('div', 'leaflet-bar leaflet-control-measure');
var link = L.DomUtil.create('a', 'leaflet-control-measure-link', this._container);
link.title = '测量';
L.DomUtil.create('span', '', link);
L.DomEvent
.on(this._container, 'contextmenu', L.DomEvent.stopPropagation)
.on(link, 'click', L.DomEvent.stopPropagation)
.on(link, 'click', function() {
if (_this._finished) { //开启新的测量
_this.start();
} else {
_this._finished = true;
}
})
// _this.start();
},
start: function() {
var _this = this;
_this._finished = false;
L.DomUtil.addClass(_this._container, 'active');
_this._addMeasureGroup();
},
_addMeasureGroup: function() {
var _this = this;
if (!_this._initialized) {
_this._measureGroup = new L.featureGroup();
_this._measureGroup.addTo(this._map);
_this._initialized = true;
}
if (_this.isNewElevation) {
_this._lC++;
_this._measureObjs[_this._lC] = new L.FeatureGroup();
_this._measureObjs[_this._lC].addTo(_this._measureGroup);
_this.isNewElevation = false;
_this._measureObjs[_this._lC].measurePoints = [];
}
_this.tmpMarkers = [];
//关闭地图双击事件
map2DViewer.map.doubleClickZoom.disable();
//监听地图单击事件
map2DViewer.map.on('click', _this._onClickPoint, this);
//监听鼠标移动事件
map2DViewer.map.on('mousemove', _this._mousemove, this);
},
_mousemove: function(e) {
var _this = this;
e.latlng = _this.latlngRectifying(e);
if (_this.moveMarker) {
_this.moveMarker.setLatLng(e.latlng);
if (_this._measureObjs[_this._lC].polyline) {
_this._measureObjs[_this._lC].measurePoints.push([e.latlng.lat, e.latlng.lng]);
var points = _this._measureObjs[_this._lC].measurePoints;
if (_this._measureObjs[_this._lC].measurePoints.length == 2) {
var radius = L.latLng(points[1]).distanceTo(L.latLng(points[0]));
_this._measureObjs[_this._lC].circle.setRadius(radius);
} else if (_this._measureObjs[_this._lC].measurePoints.length == 3 && e.latlng.indexMarker == 1) {
_this._measureObjs[_this._lC].circle.setStyle({
opacity: 1
})
} else {
_this._measureObjs[_this._lC].circle.setStyle({
opacity: 0
})
}
if (_this._measureObjs[_this._lC].measurePoints.length > 2) {
var coors = _.clone(_this._measureObjs[_this._lC].measurePoints);
coors.push(_this._measureObjs[_this._lC].measurePoints[_this._measureObjs[_this._lC].measurePoints.length - 1]);
if (_this._measureObjs[_this._lC].polygon) {
_this._measureObjs[_this._lC].polygon.setLatLngs([coors]);
} else {
_this._measureObjs[_this._lC].polygon = L.polygon([coors], {
color: "#fff",
weight: 0,
fillColor: "#fff",
fillOpacity: 0.3
}).addTo(_this._measureObjs[_this._lC]);
}
}
_this._measureObjs[_this._lC].polyline.setLatLngs(points);
//实时计算测量数据
var moveData = _.clone(points);
_this._moveInfo(moveData);
_this._measureObjs[_this._lC].measurePoints.pop();
}
} else {
_this.moveMarker = L.circleMarker(e.latlng, {
radius: 10,
color: "#f00"
}).addTo(_this._map)
}
},
//测量时,根据鼠标移动点位信息
_moveInfo: function(data) {
var _this = this;
var lineDistance = 0;
for (var i = 1; i < data.length; i++) {
var curcoor = data[i];
var prePoint = data[i - 1];
lineDistance = lineDistance + L.latLng(curcoor).distanceTo(prePoint);
var lineDistanceStr = lineDistance > 1000 ? (lineDistance / 1000).toFixed(2) + '公里' : Math.ceil(lineDistance) + '米';
if (i == data.length - 1) {
var pointAngle = L.Util.getAngleByLatLng(prePoint[1], prePoint[0], curcoor[1], curcoor[0]);
}
}
//添加分段信息
var oLabelObj = L.DomUtil.create('div', 'measure-content');
var pointText = L.DomUtil.create('span', 'measure-result-text');
pointText.innerHTML = lineDistanceStr + '
' + pointAngle + '度';
oLabelObj.appendChild(pointText);
if (data.length > 1) {
if (_this.tmpMarkers[data.length - 2]) { //如果最后一个点存在,更新最后一个点信息
_this.tmpMarkers[data.length - 2].setLatLng(data[data.length - 1]);
_this.tmpMarkers[data.length - 2].label.setContent(oLabelObj);
} else { //如果最后一个点不存在,创建点信息
var marker = L.marker(data[data.length - 1], { icon: L.divIcon({ className: 'measuremarker', iconSize: [4, 4] }) });
marker.bindLabel(oLabelObj, { noHide: true, clickable: true, className: 'measure-tip', offset: [0, 0] });
marker.addTo(_this._measureObjs[_this._lC]);
_this.tmpMarkers.push(marker);
}
}
},
/**
* 通过坐标点计算面积
* @type {Function}
* @returns {Number} 面积
* @private
*/
_getArea: function(_lc) {
var _this = this;
var latLngs = _this._measureObjs[_lc].measurePoints;
var pointsCount = latLngs.length,
area = 0.0,
d2r = Math.PI / 180,
p1, p2;
if (pointsCount > 2) {
for (var i = 0; i < pointsCount; i++) {
p1 = latLngs[i];
p2 = latLngs[(i + 1) % pointsCount];
area += ((p2[1] - p1[1]) * d2r) *
(2 + Math.sin(p1[0] * d2r) + Math.sin(p2[0] * d2r));
}
area = area * 6378137.0 * 6378137.0 / 2.0;
}
area = Math.abs(area);
if (area > 1000000) {
area = (area * 0.000001).toFixed(2) + ' 平方公里';
} else {
area = area.toFixed(2) + ' 米²';
}
return area;
},
latlngRectifying: function(e) {
var _this = this;
var curLatlngs = [];
var curpx = e.layerPoint;
var length = _this._measureObjs[_this._lC] ? _this._measureObjs[_this._lC].measurePoints.length : 0;
var latlng = e.latlng;
if (length > 0) {
curLatlngs.push({
latlng: _this._measureObjs[_this._lC].measurePoints[0],
px: _this._map.latLngToLayerPoint(_this._measureObjs[_this._lC].measurePoints[0])
})
curLatlngs.push({
latlng: _this._measureObjs[_this._lC].measurePoints[length - 1],
px: _this._map.latLngToLayerPoint(_this._measureObjs[_this._lC].measurePoints[length - 1])
})
}
for (var i = 0; i < curLatlngs.length; i++) {
var dispx = Math.sqrt((curpx.x - curLatlngs[i].px.x) * (curpx.x - curLatlngs[i].px.x) + (curpx.y - curLatlngs[i].px.y) * (curpx.y - curLatlngs[i].px.y));
if (dispx < 10) {
latlng = L.latLng(curLatlngs[i].latlng);
latlng.reset = true;
latlng.indexMarker = i;
break;
}
}
return latlng;
},
_onClickPoint: function(e) {
var _this = this;
e.latlng = _this.latlngRectifying(e);
if (!e.latlng.reset) {
_this._measureObjs[_this._lC].measurePoints.push([e.latlng.lat, e.latlng.lng]);
} else {
if (e.latlng.indexMarker == 0) {
if (_this._measureObjs[_this._lC].polygon) {
_this._measureObjs[_this._lC].measurePoints.push([e.latlng.lat, e.latlng.lng]);
_this._measureObjs[_this._lC].polygon.setLatLngs(_this._measureObjs[_this._lC].measurePoints);
_this._measureObjs[_this._lC].polygon.setStyle({
fillColor: "#f00",
color: "#f00",
weight: 0,
fillOpacity: 0.3
});
} else {
_this._measureObjs[_this._lC].removeLayer(_this._measureObjs[_this._lC].circle);
_this._measureObjs[_this._lC].removeLayer(_this._measureObjs[_this._lC].polyline);
}
} else {
_this._measureObjs[_this._lC].removeLayer(_this._measureObjs[_this._lC].polygon);
_this._measureObjs[_this._lC].polygon = null;
}
_this._onFinishClick();
}
if (_this._measureObjs[_this._lC].measurePoints.length == 1 && !_this._finished) {
var latlngs = [
[e.latlng.lat, e.latlng.lng],
[e.latlng.lat, e.latlng.lng]
];
_this._measureObjs[_this._lC].polyline = L.polyline(latlngs, { color: 'red', dashArray: 10 }).addTo(_this._measureObjs[_this._lC]);
_this._measureObjs[_this._lC].circle = L.circle([e.latlng.lat, e.latlng.lng], { radius: 0, color: 'red', fillOpacity: 0 }).addTo(_this._measureObjs[_this._lC]);
} else {
// _this._measureObjs[_this._lC].removeLayer(_this._measureObjs[_this._lC].circle);
}
},
_onFinishClick: function() {
_this = this;
//关闭地图双击事件
map2DViewer.map.doubleClickZoom.enable();
//监听地图单击事件
map2DViewer.map.off('click', _this._onClickPoint, this);
//监听鼠标移动事件
map2DViewer.map.off('mousemove', _this._mousemove, this);
_this.isNewElevation = true;
_this._finished = true;
_this._map.removeLayer(_this.moveMarker);
_this.moveMarker = null;
for (var i = 0; i < _this.tmpMarkers.length; i++) {
_this._measureObjs[_this._lC].removeLayer(_this.tmpMarkers[i]);
}
_this.tmpMarkers = [];
//根据点集合渲染marker点
var coorslength = _this._measureObjs[_this._lC].measurePoints.length;
_this._measureObjs[_this._lC].markerObjs = [];
var lineDistance = 0;
if (coorslength > 1) {
for (var i = 0; i < coorslength; i++) {
var curcoor = _this._measureObjs[_this._lC].measurePoints[i];
var marker = L.marker(curcoor, { draggable: true, icon: L.divIcon({ className: 'measuremarker', iconSize: [10, 10] }) });
if (i > 0) {
var prePoint = _this._measureObjs[_this._lC].measurePoints[i - 1];
lineDistance = lineDistance + L.latLng(curcoor).distanceTo(prePoint);
var lineDistanceStr = lineDistance > 1000 ? (lineDistance / 1000).toFixed(2) + '公里' : Math.ceil(lineDistance) + '米';
var pointAngle = L.Util.getAngleByLatLng(prePoint[1], prePoint[0], curcoor[1], curcoor[0]);
//添加分段信息
var oLabelObj = L.DomUtil.create('div', 'measure-content');
var delLabel = L.DomUtil.create('div', 'measure-ico-del');
var saveLabel = L.DomUtil.create('div', 'measure-ico-save');
var pointText = L.DomUtil.create('span', 'measure-result-text');
pointText.innerHTML = lineDistanceStr + '
' + pointAngle + '度';
delLabel.lC = _this._lC;
saveLabel.lC = _this._lC;
L.DomEvent.on(delLabel, 'click', function(e) {
L.DomEvent.stopPropagation(e);
_this.del(delLabel.lC)
});
L.DomEvent.on(saveLabel, 'click', function(e) {
L.DomEvent.stopPropagation(e);
map2DViewer.map.fire('draw-result', {
distance: _this._measureObjs[delLabel.lC].distance,
points: _this._measureObjs[delLabel.lC].measurePoints,
area: _this._measureObjs[delLabel.lC].area || 0,
LC: delLabel.lC
});
});
if (i == coorslength - 1) {
//测量面积
if (_this._measureObjs[_this._lC].polygon) {
var area = _this._getArea(_this._lC);
_this._measureObjs[_this._lC].area = area;
pointText.innerHTML = lineDistanceStr + '
' + pointAngle + '度' + '
' + area;
}
oLabelObj.appendChild(delLabel);
oLabelObj.appendChild(saveLabel);
}
oLabelObj.appendChild(pointText);
marker.bindLabel(oLabelObj, { noHide: true, clickable: true, className: 'measure-tip', offset: [0, 0] })
}
marker.LC = _this._lC;
marker.LIndex = i;
marker.addTo(_this._measureObjs[_this._lC]);
_this._measureObjs[_this._lC].markerObjs.push(marker);
if (!(i == 0 && _this._measureObjs[_this._lC].polygon)) {
marker.on("move", function(e) {
_this._renderMeasure({
LC: e.target.LC,
LIndex: e.target.LIndex,
latlng: e.latlng
});
})
}
}
}else{
var curcoor = _this._measureObjs[_this._lC].measurePoints[0];
var myIcon = L.icon({
iconUrl: this.options.iconUrl,
iconSize: [25,41],
iconAnchor: [12, 41]
});
var marker = L.marker(curcoor, { draggable: true, icon: myIcon });
var oLabelObj = L.DomUtil.create('div', 'measure-content');
var delLabel = L.DomUtil.create('div', 'measure-ico-del');
var saveLabel = L.DomUtil.create('div', 'measure-ico-save');
delLabel.lC = _this._lC;
saveLabel.lC = _this._lC;
L.DomEvent.on(delLabel, 'click', function(e) {
L.DomEvent.stopPropagation(e);
_this.del(delLabel.lC)
});
L.DomEvent.on(saveLabel, 'click', function(e) {
L.DomEvent.stopPropagation(e);
map2DViewer.map.fire('draw-result', {
distance: _this._measureObjs[delLabel.lC].distance,
points: _this._measureObjs[delLabel.lC].measurePoints,
area: _this._measureObjs[delLabel.lC].area || 0,
LC: delLabel.lC
});
});
oLabelObj.appendChild(delLabel);
oLabelObj.appendChild(saveLabel);
marker.bindLabel(oLabelObj, { noHide: true, clickable: true, className: 'measure-tip', offset: [0, 0] })
marker.LC = _this._lC;
marker.LIndex = i;
marker.addTo(_this._measureObjs[_this._lC]);
_this._measureObjs[_this._lC].markerObjs.push(marker);
}
_this._measureObjs[_this._lC].distance = lineDistance;
},
_renderMeasure: function(data) {
var _this = this;
var latlng = [data.latlng.lat, data.latlng.lng];
if (_this._measureObjs[data.LC].measurePoints.length == 1) {
return false;
}
_this._measureObjs[data.LC].measurePoints[data.LIndex] = latlng;
var curlength = _this._measureObjs[data.LC].measurePoints.length;
//如果是面,第一个点和最后一个点位置同时改变
if (_this._measureObjs[data.LC].polygon) {
if (data.LIndex == 0) {
_this._measureObjs[data.LC].measurePoints[curlength - 1] = latlng;
_this._measureObjs[_this._lC].markerObjs[curlength - 1].setLatLng(latlng);
}
if (data.LIndex == curlength - 1) {
_this._measureObjs[data.LC].measurePoints[0] = latlng;
_this._measureObjs[_this._lC].markerObjs[0].setLatLng(latlng);
}
}
var points = _this._measureObjs[data.LC].measurePoints;
//更新circle
var radius = L.latLng(points[1]).distanceTo(L.latLng(points[0]));
_this._measureObjs[data.LC].circle.setRadius(radius);
_this._measureObjs[data.LC].circle.setLatLng(points[0]);
if (points.length == 2) {
_this._measureObjs[data.LC].circle.setStyle({
opacity: 1
})
}
//更新线
_this._measureObjs[data.LC].polyline.setLatLngs(points);
//更新面
if (_this._measureObjs[data.LC].polygon) {
_this._measureObjs[data.LC].polygon.setLatLngs([points]);
}
var lineDistance = 0;
var coorslength = _this._measureObjs[data.LC].measurePoints.length;
for (var i = 1; i < coorslength; i++) {
var curcoor = _this._measureObjs[data.LC].measurePoints[i];
var prePoint = _this._measureObjs[data.LC].measurePoints[i - 1];
lineDistance = lineDistance + L.latLng(curcoor).distanceTo(prePoint);
var lineDistanceStr = lineDistance > 1000 ? (lineDistance / 1000).toFixed(2) + '公里' : Math.ceil(lineDistance) + '米';
var pointAngle = L.Util.getAngleByLatLng(prePoint[1], prePoint[0], curcoor[1], curcoor[0]);
//添加分段信息
var oLabelObj = L.DomUtil.create('div', 'measure-content');
var delLabel = L.DomUtil.create('div', 'measure-ico-del');
var pointText = L.DomUtil.create('span', 'measure-result-text');
pointText.innerHTML = lineDistanceStr + '
' + pointAngle + '度';
delLabel.lC = _this._lC;
L.DomEvent.on(delLabel, 'click', function(e) {
L.DomEvent.stopPropagation(e);
_this.del(delLabel.lC)
});
if (i == coorslength - 1) {
oLabelObj.appendChild(delLabel);
//测量面积
if (_this._measureObjs[data.LC].polygon) {
var area = _this._getArea(data.LC);
_this._measureObjs[data.LC].area
pointText.innerHTML = lineDistanceStr + '
' + pointAngle + '度' + '
' + area;
}
}
oLabelObj.appendChild(pointText);
_this._measureObjs[_this._lC].distance = lineDistance;
_this._measureObjs[data.LC].markerObjs[i].label.setContent(oLabelObj);
}
},
/**
* 删除对应lC的测距
*/
del: function(lC) {
var _this = this;
if (_this._measureObjs[lC]) {
_this._measureGroup.removeLayer(_this._measureObjs[lC]);
delete _this._measureObjs[lC];
}
},
});
/**
* 测量工具
*/
map2DViewer.drawToolFire = function(data) {
console.log(data);
};
map2DViewer.setDrawTool = function(options) {
var defaultData = {
action: 'add',
position: 'topleft',
offset: [10, 10],
background: "#fff",
color: "#000",
font_size: "14px",
closeButton: true
}
_.merge(defaultData, options);
switch (defaultData.action) {
case 'add':
this.measureTool = new L.Control.Draw({
position: defaultData.position,
offset: defaultData.offset,
background: defaultData.background,
color: defaultData.color,
font_size: defaultData.font_size,
closeButton: defaultData.closeButton,
iconUrl:"http://localhost:888/scripts/vendor/leaflet/images/marker-icon.png"
}).addTo(this.map);
this.map.on('draw-result', map2DViewer.drawToolFire);
return this.distanceTool;
break;
case 'remove':
this.map.off('draw-result', map2DViewer.drawToolFire);
break;
case 'start':
this.measureTool.start();
break;
}
}