leaflet.draw.js 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527
  1. L.Control.Draw = L.Control.extend({
  2. //是否初始化
  3. _initialized: false,
  4. //统计
  5. _lC: 0,
  6. //测量对象集合
  7. _measureObjs: {},
  8. //是否完成当前测绘
  9. _finished: true,
  10. //新测量
  11. isNewElevation: true,
  12. moveMarker: false,
  13. //测量参数
  14. options: {
  15. position: 'topright',
  16. autoZIndex: true,
  17. offset: [10, 10],
  18. background: "#000",
  19. color: "#fff",
  20. size: 14,
  21. closeButton: true,
  22. iconUrl:'./images/marker-icon.png'
  23. },
  24. initialize: function(options) {
  25. L.setOptions(this, options);
  26. return this;
  27. },
  28. onAdd: function(map) {
  29. this._map = map;
  30. this._createControl();
  31. switch (this.options.position) {
  32. case 'topleft':
  33. this._container.style.marginLeft = this.options.offset[0] + 'px';
  34. this._container.style.marginTop = this.options.offset[1] + 'px';
  35. break;
  36. case 'topright':
  37. this._container.style.marginRight = this.options.offset[0] + 'px';
  38. this._container.style.marginTop = this.options.offset[1] + 'px';
  39. break;
  40. case 'bottomleft':
  41. this._container.style.marginLeft = this.options.offset[0] + 'px';
  42. this._container.style.marginBottom = this.options.offset[1] + 'px';
  43. break;
  44. case 'bottomright':
  45. this._container.style.marginRight = this.options.offset[0] + 'px';
  46. this._container.style.marginBottom = this.options.offset[1] + 'px';
  47. break;
  48. }
  49. return this._container;
  50. },
  51. _createControl: function() {
  52. var _this = this;
  53. this._container = L.DomUtil.create('div', 'leaflet-bar leaflet-control-measure');
  54. var link = L.DomUtil.create('a', 'leaflet-control-measure-link', this._container);
  55. link.title = '测量';
  56. L.DomUtil.create('span', '', link);
  57. L.DomEvent
  58. .on(this._container, 'contextmenu', L.DomEvent.stopPropagation)
  59. .on(link, 'click', L.DomEvent.stopPropagation)
  60. .on(link, 'click', function() {
  61. if (_this._finished) { //开启新的测量
  62. _this.start();
  63. } else {
  64. _this._finished = true;
  65. }
  66. })
  67. // _this.start();
  68. },
  69. start: function() {
  70. var _this = this;
  71. _this._finished = false;
  72. L.DomUtil.addClass(_this._container, 'active');
  73. _this._addMeasureGroup();
  74. },
  75. _addMeasureGroup: function() {
  76. var _this = this;
  77. if (!_this._initialized) {
  78. _this._measureGroup = new L.featureGroup();
  79. _this._measureGroup.addTo(this._map);
  80. _this._initialized = true;
  81. }
  82. if (_this.isNewElevation) {
  83. _this._lC++;
  84. _this._measureObjs[_this._lC] = new L.FeatureGroup();
  85. _this._measureObjs[_this._lC].addTo(_this._measureGroup);
  86. _this.isNewElevation = false;
  87. _this._measureObjs[_this._lC].measurePoints = [];
  88. }
  89. _this.tmpMarkers = [];
  90. //关闭地图双击事件
  91. map2DViewer.map.doubleClickZoom.disable();
  92. //监听地图单击事件
  93. map2DViewer.map.on('click', _this._onClickPoint, this);
  94. //监听鼠标移动事件
  95. map2DViewer.map.on('mousemove', _this._mousemove, this);
  96. },
  97. _mousemove: function(e) {
  98. var _this = this;
  99. e.latlng = _this.latlngRectifying(e);
  100. if (_this.moveMarker) {
  101. _this.moveMarker.setLatLng(e.latlng);
  102. if (_this._measureObjs[_this._lC].polyline) {
  103. _this._measureObjs[_this._lC].measurePoints.push([e.latlng.lat, e.latlng.lng]);
  104. var points = _this._measureObjs[_this._lC].measurePoints;
  105. if (_this._measureObjs[_this._lC].measurePoints.length == 2) {
  106. var radius = L.latLng(points[1]).distanceTo(L.latLng(points[0]));
  107. _this._measureObjs[_this._lC].circle.setRadius(radius);
  108. } else if (_this._measureObjs[_this._lC].measurePoints.length == 3 && e.latlng.indexMarker == 1) {
  109. _this._measureObjs[_this._lC].circle.setStyle({
  110. opacity: 1
  111. })
  112. } else {
  113. _this._measureObjs[_this._lC].circle.setStyle({
  114. opacity: 0
  115. })
  116. }
  117. if (_this._measureObjs[_this._lC].measurePoints.length > 2) {
  118. var coors = _.clone(_this._measureObjs[_this._lC].measurePoints);
  119. coors.push(_this._measureObjs[_this._lC].measurePoints[_this._measureObjs[_this._lC].measurePoints.length - 1]);
  120. if (_this._measureObjs[_this._lC].polygon) {
  121. _this._measureObjs[_this._lC].polygon.setLatLngs([coors]);
  122. } else {
  123. _this._measureObjs[_this._lC].polygon = L.polygon([coors], {
  124. color: "#fff",
  125. weight: 0,
  126. fillColor: "#fff",
  127. fillOpacity: 0.3
  128. }).addTo(_this._measureObjs[_this._lC]);
  129. }
  130. }
  131. _this._measureObjs[_this._lC].polyline.setLatLngs(points);
  132. //实时计算测量数据
  133. var moveData = _.clone(points);
  134. _this._moveInfo(moveData);
  135. _this._measureObjs[_this._lC].measurePoints.pop();
  136. }
  137. } else {
  138. _this.moveMarker = L.circleMarker(e.latlng, {
  139. radius: 10,
  140. color: "#f00"
  141. }).addTo(_this._map)
  142. }
  143. },
  144. //测量时,根据鼠标移动点位信息
  145. _moveInfo: function(data) {
  146. var _this = this;
  147. var lineDistance = 0;
  148. for (var i = 1; i < data.length; i++) {
  149. var curcoor = data[i];
  150. var prePoint = data[i - 1];
  151. lineDistance = lineDistance + L.latLng(curcoor).distanceTo(prePoint);
  152. var lineDistanceStr = lineDistance > 1000 ? (lineDistance / 1000).toFixed(2) + '公里' : Math.ceil(lineDistance) + '米';
  153. if (i == data.length - 1) {
  154. var pointAngle = L.Util.getAngleByLatLng(prePoint[1], prePoint[0], curcoor[1], curcoor[0]);
  155. }
  156. }
  157. //添加分段信息
  158. var oLabelObj = L.DomUtil.create('div', 'measure-content');
  159. var pointText = L.DomUtil.create('span', 'measure-result-text');
  160. pointText.innerHTML = lineDistanceStr + '<br/>' + pointAngle + '度';
  161. oLabelObj.appendChild(pointText);
  162. if (data.length > 1) {
  163. if (_this.tmpMarkers[data.length - 2]) { //如果最后一个点存在,更新最后一个点信息
  164. _this.tmpMarkers[data.length - 2].setLatLng(data[data.length - 1]);
  165. _this.tmpMarkers[data.length - 2].label.setContent(oLabelObj);
  166. } else { //如果最后一个点不存在,创建点信息
  167. var marker = L.marker(data[data.length - 1], { icon: L.divIcon({ className: 'measuremarker', iconSize: [4, 4] }) });
  168. marker.bindLabel(oLabelObj, { noHide: true, clickable: true, className: 'measure-tip', offset: [0, 0] });
  169. marker.addTo(_this._measureObjs[_this._lC]);
  170. _this.tmpMarkers.push(marker);
  171. }
  172. }
  173. },
  174. /**
  175. * 通过坐标点计算面积
  176. * @type {Function}
  177. * @returns {Number} 面积
  178. * @private
  179. */
  180. _getArea: function(_lc) {
  181. var _this = this;
  182. var latLngs = _this._measureObjs[_lc].measurePoints;
  183. var pointsCount = latLngs.length,
  184. area = 0.0,
  185. d2r = Math.PI / 180,
  186. p1, p2;
  187. if (pointsCount > 2) {
  188. for (var i = 0; i < pointsCount; i++) {
  189. p1 = latLngs[i];
  190. p2 = latLngs[(i + 1) % pointsCount];
  191. area += ((p2[1] - p1[1]) * d2r) *
  192. (2 + Math.sin(p1[0] * d2r) + Math.sin(p2[0] * d2r));
  193. }
  194. area = area * 6378137.0 * 6378137.0 / 2.0;
  195. }
  196. area = Math.abs(area);
  197. if (area > 1000000) {
  198. area = (area * 0.000001).toFixed(2) + ' 平方公里';
  199. } else {
  200. area = area.toFixed(2) + ' 米&sup2;';
  201. }
  202. return area;
  203. },
  204. latlngRectifying: function(e) {
  205. var _this = this;
  206. var curLatlngs = [];
  207. var curpx = e.layerPoint;
  208. var length = _this._measureObjs[_this._lC] ? _this._measureObjs[_this._lC].measurePoints.length : 0;
  209. var latlng = e.latlng;
  210. if (length > 0) {
  211. curLatlngs.push({
  212. latlng: _this._measureObjs[_this._lC].measurePoints[0],
  213. px: _this._map.latLngToLayerPoint(_this._measureObjs[_this._lC].measurePoints[0])
  214. })
  215. curLatlngs.push({
  216. latlng: _this._measureObjs[_this._lC].measurePoints[length - 1],
  217. px: _this._map.latLngToLayerPoint(_this._measureObjs[_this._lC].measurePoints[length - 1])
  218. })
  219. }
  220. for (var i = 0; i < curLatlngs.length; i++) {
  221. 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));
  222. if (dispx < 10) {
  223. latlng = L.latLng(curLatlngs[i].latlng);
  224. latlng.reset = true;
  225. latlng.indexMarker = i;
  226. break;
  227. }
  228. }
  229. return latlng;
  230. },
  231. _onClickPoint: function(e) {
  232. var _this = this;
  233. e.latlng = _this.latlngRectifying(e);
  234. if (!e.latlng.reset) {
  235. _this._measureObjs[_this._lC].measurePoints.push([e.latlng.lat, e.latlng.lng]);
  236. } else {
  237. if (e.latlng.indexMarker == 0) {
  238. if (_this._measureObjs[_this._lC].polygon) {
  239. _this._measureObjs[_this._lC].measurePoints.push([e.latlng.lat, e.latlng.lng]);
  240. _this._measureObjs[_this._lC].polygon.setLatLngs(_this._measureObjs[_this._lC].measurePoints);
  241. _this._measureObjs[_this._lC].polygon.setStyle({
  242. fillColor: "#f00",
  243. color: "#f00",
  244. weight: 0,
  245. fillOpacity: 0.3
  246. });
  247. } else {
  248. _this._measureObjs[_this._lC].removeLayer(_this._measureObjs[_this._lC].circle);
  249. _this._measureObjs[_this._lC].removeLayer(_this._measureObjs[_this._lC].polyline);
  250. }
  251. } else {
  252. _this._measureObjs[_this._lC].removeLayer(_this._measureObjs[_this._lC].polygon);
  253. _this._measureObjs[_this._lC].polygon = null;
  254. }
  255. _this._onFinishClick();
  256. }
  257. if (_this._measureObjs[_this._lC].measurePoints.length == 1 && !_this._finished) {
  258. var latlngs = [
  259. [e.latlng.lat, e.latlng.lng],
  260. [e.latlng.lat, e.latlng.lng]
  261. ];
  262. _this._measureObjs[_this._lC].polyline = L.polyline(latlngs, { color: 'red', dashArray: 10 }).addTo(_this._measureObjs[_this._lC]);
  263. _this._measureObjs[_this._lC].circle = L.circle([e.latlng.lat, e.latlng.lng], { radius: 0, color: 'red', fillOpacity: 0 }).addTo(_this._measureObjs[_this._lC]);
  264. } else {
  265. // _this._measureObjs[_this._lC].removeLayer(_this._measureObjs[_this._lC].circle);
  266. }
  267. },
  268. _onFinishClick: function() {
  269. _this = this;
  270. //关闭地图双击事件
  271. map2DViewer.map.doubleClickZoom.enable();
  272. //监听地图单击事件
  273. map2DViewer.map.off('click', _this._onClickPoint, this);
  274. //监听鼠标移动事件
  275. map2DViewer.map.off('mousemove', _this._mousemove, this);
  276. _this.isNewElevation = true;
  277. _this._finished = true;
  278. _this._map.removeLayer(_this.moveMarker);
  279. _this.moveMarker = null;
  280. for (var i = 0; i < _this.tmpMarkers.length; i++) {
  281. _this._measureObjs[_this._lC].removeLayer(_this.tmpMarkers[i]);
  282. }
  283. _this.tmpMarkers = [];
  284. //根据点集合渲染marker点
  285. var coorslength = _this._measureObjs[_this._lC].measurePoints.length;
  286. _this._measureObjs[_this._lC].markerObjs = [];
  287. var lineDistance = 0;
  288. if (coorslength > 1) {
  289. for (var i = 0; i < coorslength; i++) {
  290. var curcoor = _this._measureObjs[_this._lC].measurePoints[i];
  291. var marker = L.marker(curcoor, { draggable: true, icon: L.divIcon({ className: 'measuremarker', iconSize: [10, 10] }) });
  292. if (i > 0) {
  293. var prePoint = _this._measureObjs[_this._lC].measurePoints[i - 1];
  294. lineDistance = lineDistance + L.latLng(curcoor).distanceTo(prePoint);
  295. var lineDistanceStr = lineDistance > 1000 ? (lineDistance / 1000).toFixed(2) + '公里' : Math.ceil(lineDistance) + '米';
  296. var pointAngle = L.Util.getAngleByLatLng(prePoint[1], prePoint[0], curcoor[1], curcoor[0]);
  297. //添加分段信息
  298. var oLabelObj = L.DomUtil.create('div', 'measure-content');
  299. var delLabel = L.DomUtil.create('div', 'measure-ico-del');
  300. var saveLabel = L.DomUtil.create('div', 'measure-ico-save');
  301. var pointText = L.DomUtil.create('span', 'measure-result-text');
  302. pointText.innerHTML = lineDistanceStr + '<br/>' + pointAngle + '度';
  303. delLabel.lC = _this._lC;
  304. saveLabel.lC = _this._lC;
  305. L.DomEvent.on(delLabel, 'click', function(e) {
  306. L.DomEvent.stopPropagation(e);
  307. _this.del(delLabel.lC)
  308. });
  309. L.DomEvent.on(saveLabel, 'click', function(e) {
  310. L.DomEvent.stopPropagation(e);
  311. map2DViewer.map.fire('draw-result', {
  312. distance: _this._measureObjs[delLabel.lC].distance,
  313. points: _this._measureObjs[delLabel.lC].measurePoints,
  314. area: _this._measureObjs[delLabel.lC].area || 0,
  315. LC: delLabel.lC
  316. });
  317. });
  318. if (i == coorslength - 1) {
  319. //测量面积
  320. if (_this._measureObjs[_this._lC].polygon) {
  321. var area = _this._getArea(_this._lC);
  322. _this._measureObjs[_this._lC].area = area;
  323. pointText.innerHTML = lineDistanceStr + '<br/>' + pointAngle + '度' + '<br/>' + area;
  324. }
  325. oLabelObj.appendChild(delLabel);
  326. oLabelObj.appendChild(saveLabel);
  327. }
  328. oLabelObj.appendChild(pointText);
  329. marker.bindLabel(oLabelObj, { noHide: true, clickable: true, className: 'measure-tip', offset: [0, 0] })
  330. }
  331. marker.LC = _this._lC;
  332. marker.LIndex = i;
  333. marker.addTo(_this._measureObjs[_this._lC]);
  334. _this._measureObjs[_this._lC].markerObjs.push(marker);
  335. if (!(i == 0 && _this._measureObjs[_this._lC].polygon)) {
  336. marker.on("move", function(e) {
  337. _this._renderMeasure({
  338. LC: e.target.LC,
  339. LIndex: e.target.LIndex,
  340. latlng: e.latlng
  341. });
  342. })
  343. }
  344. }
  345. }else{
  346. var curcoor = _this._measureObjs[_this._lC].measurePoints[0];
  347. var myIcon = L.icon({
  348. iconUrl: this.options.iconUrl,
  349. iconSize: [25,41],
  350. iconAnchor: [12, 41]
  351. });
  352. var marker = L.marker(curcoor, { draggable: true, icon: myIcon });
  353. var oLabelObj = L.DomUtil.create('div', 'measure-content');
  354. var delLabel = L.DomUtil.create('div', 'measure-ico-del');
  355. var saveLabel = L.DomUtil.create('div', 'measure-ico-save');
  356. delLabel.lC = _this._lC;
  357. saveLabel.lC = _this._lC;
  358. L.DomEvent.on(delLabel, 'click', function(e) {
  359. L.DomEvent.stopPropagation(e);
  360. _this.del(delLabel.lC)
  361. });
  362. L.DomEvent.on(saveLabel, 'click', function(e) {
  363. L.DomEvent.stopPropagation(e);
  364. map2DViewer.map.fire('draw-result', {
  365. distance: _this._measureObjs[delLabel.lC].distance,
  366. points: _this._measureObjs[delLabel.lC].measurePoints,
  367. area: _this._measureObjs[delLabel.lC].area || 0,
  368. LC: delLabel.lC
  369. });
  370. });
  371. oLabelObj.appendChild(delLabel);
  372. oLabelObj.appendChild(saveLabel);
  373. marker.bindLabel(oLabelObj, { noHide: true, clickable: true, className: 'measure-tip', offset: [0, 0] })
  374. marker.LC = _this._lC;
  375. marker.LIndex = i;
  376. marker.addTo(_this._measureObjs[_this._lC]);
  377. _this._measureObjs[_this._lC].markerObjs.push(marker);
  378. }
  379. _this._measureObjs[_this._lC].distance = lineDistance;
  380. },
  381. _renderMeasure: function(data) {
  382. var _this = this;
  383. var latlng = [data.latlng.lat, data.latlng.lng];
  384. if (_this._measureObjs[data.LC].measurePoints.length == 1) {
  385. return false;
  386. }
  387. _this._measureObjs[data.LC].measurePoints[data.LIndex] = latlng;
  388. var curlength = _this._measureObjs[data.LC].measurePoints.length;
  389. //如果是面,第一个点和最后一个点位置同时改变
  390. if (_this._measureObjs[data.LC].polygon) {
  391. if (data.LIndex == 0) {
  392. _this._measureObjs[data.LC].measurePoints[curlength - 1] = latlng;
  393. _this._measureObjs[_this._lC].markerObjs[curlength - 1].setLatLng(latlng);
  394. }
  395. if (data.LIndex == curlength - 1) {
  396. _this._measureObjs[data.LC].measurePoints[0] = latlng;
  397. _this._measureObjs[_this._lC].markerObjs[0].setLatLng(latlng);
  398. }
  399. }
  400. var points = _this._measureObjs[data.LC].measurePoints;
  401. //更新circle
  402. var radius = L.latLng(points[1]).distanceTo(L.latLng(points[0]));
  403. _this._measureObjs[data.LC].circle.setRadius(radius);
  404. _this._measureObjs[data.LC].circle.setLatLng(points[0]);
  405. if (points.length == 2) {
  406. _this._measureObjs[data.LC].circle.setStyle({
  407. opacity: 1
  408. })
  409. }
  410. //更新线
  411. _this._measureObjs[data.LC].polyline.setLatLngs(points);
  412. //更新面
  413. if (_this._measureObjs[data.LC].polygon) {
  414. _this._measureObjs[data.LC].polygon.setLatLngs([points]);
  415. }
  416. var lineDistance = 0;
  417. var coorslength = _this._measureObjs[data.LC].measurePoints.length;
  418. for (var i = 1; i < coorslength; i++) {
  419. var curcoor = _this._measureObjs[data.LC].measurePoints[i];
  420. var prePoint = _this._measureObjs[data.LC].measurePoints[i - 1];
  421. lineDistance = lineDistance + L.latLng(curcoor).distanceTo(prePoint);
  422. var lineDistanceStr = lineDistance > 1000 ? (lineDistance / 1000).toFixed(2) + '公里' : Math.ceil(lineDistance) + '米';
  423. var pointAngle = L.Util.getAngleByLatLng(prePoint[1], prePoint[0], curcoor[1], curcoor[0]);
  424. //添加分段信息
  425. var oLabelObj = L.DomUtil.create('div', 'measure-content');
  426. var delLabel = L.DomUtil.create('div', 'measure-ico-del');
  427. var pointText = L.DomUtil.create('span', 'measure-result-text');
  428. pointText.innerHTML = lineDistanceStr + '<br/>' + pointAngle + '度';
  429. delLabel.lC = _this._lC;
  430. L.DomEvent.on(delLabel, 'click', function(e) {
  431. L.DomEvent.stopPropagation(e);
  432. _this.del(delLabel.lC)
  433. });
  434. if (i == coorslength - 1) {
  435. oLabelObj.appendChild(delLabel);
  436. //测量面积
  437. if (_this._measureObjs[data.LC].polygon) {
  438. var area = _this._getArea(data.LC);
  439. _this._measureObjs[data.LC].area
  440. pointText.innerHTML = lineDistanceStr + '<br/>' + pointAngle + '度' + '<br/>' + area;
  441. }
  442. }
  443. oLabelObj.appendChild(pointText);
  444. _this._measureObjs[_this._lC].distance = lineDistance;
  445. _this._measureObjs[data.LC].markerObjs[i].label.setContent(oLabelObj);
  446. }
  447. },
  448. /**
  449. * 删除对应lC的测距
  450. */
  451. del: function(lC) {
  452. var _this = this;
  453. if (_this._measureObjs[lC]) {
  454. _this._measureGroup.removeLayer(_this._measureObjs[lC]);
  455. delete _this._measureObjs[lC];
  456. }
  457. },
  458. });
  459. /**
  460. * 测量工具
  461. */
  462. map2DViewer.drawToolFire = function(data) {
  463. console.log(data);
  464. };
  465. map2DViewer.setDrawTool = function(options) {
  466. var defaultData = {
  467. action: 'add',
  468. position: 'topleft',
  469. offset: [10, 10],
  470. background: "#fff",
  471. color: "#000",
  472. font_size: "14px",
  473. closeButton: true
  474. }
  475. _.merge(defaultData, options);
  476. switch (defaultData.action) {
  477. case 'add':
  478. this.measureTool = new L.Control.Draw({
  479. position: defaultData.position,
  480. offset: defaultData.offset,
  481. background: defaultData.background,
  482. color: defaultData.color,
  483. font_size: defaultData.font_size,
  484. closeButton: defaultData.closeButton,
  485. iconUrl:"http://localhost:888/scripts/vendor/leaflet/images/marker-icon.png"
  486. }).addTo(this.map);
  487. this.map.on('draw-result', map2DViewer.drawToolFire);
  488. return this.distanceTool;
  489. break;
  490. case 'remove':
  491. this.map.off('draw-result', map2DViewer.drawToolFire);
  492. break;
  493. case 'start':
  494. this.measureTool.start();
  495. break;
  496. }
  497. }