leaflet.measureArea.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. L.Control.MeasureArea = L.Control.extend({
  2. //是否初始化
  3. _initialized: false,
  4. //统计
  5. _mC: 0,
  6. //marker统计
  7. AreaMarker: {},
  8. //测
  9. _measureAObjs: {},
  10. //是否已经显示测面
  11. isshowpolygonArea: false,
  12. //是否完成当前测绘
  13. _finished: true,
  14. /**
  15. * 是否是新的测量事件
  16. * @type {Boolean}
  17. * @default true
  18. * @private
  19. */
  20. _isNewMeasure: true,
  21. options: {
  22. position: 'topright',
  23. autoZIndex: true,
  24. offset: [10, 40],
  25. background: "#000",
  26. color: "#fff",
  27. size: 14,
  28. closeButton:true
  29. },
  30. initialize: function(options) {
  31. L.setOptions(this, options);
  32. return this;
  33. },
  34. onAdd: function(map) {
  35. this._map = map;
  36. this._createControl();
  37. var _this = this;
  38. //this._map.on('measure-distance-start', this.stop, this);
  39. switch (this.options.position) {
  40. case 'topleft':
  41. this._container.style.marginLeft = this.options.offset[0] + 'px';
  42. this._container.style.marginTop = this.options.offset[1] + 'px';
  43. break;
  44. case 'topright':
  45. this._container.style.marginRight = this.options.offset[0] + 'px';
  46. this._container.style.marginTop = this.options.offset[1] + 'px';
  47. break;
  48. case 'bottomleft':
  49. this._container.style.marginLeft = this.options.offset[0] + 'px';
  50. this._container.style.marginBottom = this.options.offset[1] + 'px';
  51. break;
  52. case 'bottomright':
  53. this._container.style.marginRight = this.options.offset[0] + 'px';
  54. this._container.style.marginBottom = this.options.offset[1] + 'px';
  55. break;
  56. }
  57. return this._container;
  58. },
  59. _createControl: function() {
  60. var _this = this;
  61. this._container = L.DomUtil.create('div', 'leaflet-bar leaflet-control-measure-area');
  62. var link = L.DomUtil.create('a', 'leaflet-control-measure-area-link', this._container);
  63. link.title = '测面积';
  64. L.DomUtil.create('span', '', link);
  65. L.DomEvent
  66. .on(this._container, 'contextmenu', L.DomEvent.stopPropagation)
  67. .on(link, 'click', L.DomEvent.stopPropagation)
  68. .on(link, 'click', function() {
  69. if (!_this._finished) {
  70. _this._finished = true;
  71. L.DomUtil.removeClass(_this._container, 'active');
  72. _this._removeMeasureGroup();
  73. _this._map.getContainer().style.cursor = 'auto';
  74. } else {
  75. _this._finished = false;
  76. L.DomUtil.addClass(_this._container, 'active');
  77. _this._addMeasureGroup();
  78. if (L.Browser.ie || L.Browser.firefox) {
  79. _this._map.getContainer().style.cursor = 'url(' + L.DefaultImagePath + '/cur-ruler.cur),auto';
  80. } else {
  81. _this._map.getContainer().style.cursor = 'url(' + L.DefaultImagePath + '/cur-ruler.cur) 5 5,auto';
  82. }
  83. }
  84. })
  85. },
  86. start: function() {
  87. var _this = this;
  88. if (!_this._finished) {
  89. _this._finished = true;
  90. L.DomUtil.removeClass(_this._container, 'active');
  91. _this._removeMeasureGroup();
  92. _this._map.getContainer().style.cursor = 'auto';
  93. }
  94. _this._finished = false;
  95. L.DomUtil.addClass(_this._container, 'active');
  96. _this._addMeasureGroup();
  97. if (L.Browser.ie || L.Browser.firefox) {
  98. _this._map.getContainer().style.cursor = 'url(' + L.DefaultImagePath + '/cur-ruler.cur),auto';
  99. } else {
  100. _this._map.getContainer().style.cursor = 'url(' + L.DefaultImagePath + '/cur-ruler.cur) 5 5,auto';
  101. }
  102. },
  103. _addMeasureGroup: function() {
  104. var _this = this;
  105. _this.isshowpolygonArea = false;
  106. if (!_this._initialized) {
  107. _this._measureGroup = new L.featureGroup();
  108. _this._measureGroup.addTo(_this._map);
  109. _this._initialized = true;
  110. }
  111. _this._map.doubleClickZoom.disable();
  112. _this._map.on('click', _this._onClickPoint, this);
  113. },
  114. /**
  115. * 鼠标移动重绘多边形 //todo 这里应该 新建立一个临时 坐标组
  116. * @type {Function}
  117. * @param e
  118. * @private
  119. */
  120. _onMovePoint: function(e) {
  121. var _this = this;
  122. var tempPoint = [];
  123. tempPoint = _this._measureAObjs[_this._mC].measurePoints.concat();
  124. _this._measureAObjs[_this._mC].measurePoints.push(e.latlng);
  125. _this._drawPolygon();
  126. _this._measureAObjs[_this._mC].measurePoints = tempPoint.concat();
  127. },
  128. /**
  129. * 鼠标单击添加多边形的点
  130. * @type {Function}
  131. * @param e
  132. * @private
  133. */
  134. _onClickPoint: function(e) {
  135. var _this = this;
  136. e.latlng = L.Util.formatEarthLatLng(e.latlng);
  137. if (_this._isNewMeasure) {
  138. _this._mC++;
  139. _this._measureAObjs[_this._mC] = new L.FeatureGroup();
  140. _this._measureAObjs[_this._mC].addTo(_this._measureGroup);
  141. _this._measureAObjs[_this._mC].measurePoints = [];
  142. _this._measureAObjs[_this._mC].polygon = new L.polygon([
  143. [0, 0],
  144. [0, 0],
  145. [0, 0]
  146. ], { fillColor: "blue", color: "#00b7ef", opacity: 0.8, weight: 3 });
  147. _this._measureAObjs[_this._mC].polygon.addTo(_this._measureGroup);
  148. _this._measureAObjs[_this._mC].polygon.on('click', _this._onClickPoint, this);
  149. _this._isNewMeasure = false;
  150. }
  151. _this._measureAObjs[_this._mC].measurePoints.push(e.latlng);
  152. if (_this._measureAObjs[_this._mC].measurePoints.length > 1) {
  153. _this._drawPolygon();
  154. _this._map.on('mousemove', _this._onMovePoint, this);
  155. }
  156. _this._buildMarker(e).addTo(_this._measureAObjs[_this._mC]);
  157. },
  158. /**
  159. * 鼠标双击结束多边形点添加
  160. * @type {Function}
  161. * @param e
  162. * @private
  163. */
  164. _onFinishClick: function(e) {
  165. var _this = this;
  166. _this._map.off('mousemove', _this._onMovePoint, this);
  167. _this._measureAObjs[_this._mC].measurePoints.push(e.latlng);
  168. if (_this._measureAObjs[_this._mC].measurePoints.length > 1) {
  169. _this._drawPolygon();
  170. }
  171. _this._measureAObjs[_this._mC].polygon.off('click', _this._onClickPoint, this);
  172. _this._isNewMeasure = true;
  173. if (!_this.isshowpolygonArea) {
  174. _this._countArea(e);
  175. _this.isshowpolygonArea = true;
  176. }
  177. _this._finished = true;
  178. _this._removeMeasureGroup();
  179. _this._map.getContainer().style.cursor = 'auto';
  180. _this.start();
  181. },
  182. /**
  183. * [cleanAllMeasure description]
  184. * @return {[type]} [description]
  185. */
  186. cleanAllMeasure: function() {
  187. var _this = this;
  188. for (var item in _this._measureAObjs) {
  189. _this.del(item);
  190. }
  191. },
  192. /**
  193. * 重绘多边形
  194. * @type {Function}
  195. * @private
  196. */
  197. _drawPolygon: function() {
  198. var _this = this;
  199. _this._measureAObjs[_this._mC].polygon.setLatLngs(_this._measureAObjs[_this._mC].measurePoints);
  200. _this._measureAObjs[_this._mC].polygon.redraw();
  201. },
  202. /**
  203. * 创建一个marker 并返回该marker
  204. * @type {Function}
  205. * @param obj {Object} {latlng}
  206. * @returns {L.Marker}
  207. * @private
  208. */
  209. _buildMarker: function(obj) {
  210. var _this = this;
  211. var marker = L.marker(
  212. obj.latlng, {
  213. icon: L.divIcon({
  214. //className: 'my-div-icon1',
  215. //iconUrl: L.DefaultImagePath+'/icon-linePoint.png',
  216. iconSize: [5, 5]
  217. })
  218. }
  219. );
  220. marker.on('click', function(e) {
  221. if (_this._measureAObjs[_this._mC].measurePoints.length < 2) {
  222. return false;
  223. }
  224. //与上一个点相同,测量完成
  225. if(e.latlng == _this._measureAObjs[_this._mC].measurePoints[_this._measureAObjs[_this._mC].measurePoints.length-1] ){
  226. _this._onFinishClick({ latlng: _this._measureAObjs[_this._mC].measurePoints[_this._measureAObjs[_this._mC].measurePoints.length - 1] });
  227. return false;
  228. }
  229. });
  230. _this.AreaMarker[_this._mC] = marker;
  231. return marker;
  232. },
  233. /**
  234. * 测量面积
  235. * @type {Function}
  236. * @param e
  237. * @private
  238. */
  239. _countArea: function(e) {
  240. var _this = this;
  241. var areaLabel = L.DomUtil.create('span', 'area');
  242. areaLabel.style.color = 'red';
  243. areaLabel.style.fontWeight = 'bold';
  244. areaLabel.innerHTML = '面积:' + _this._getArea();
  245. //console.log(areaLabel.innerHTML);
  246. areaLabel.mid = _this._mC;
  247. //添加结束信息
  248. var oLabelObjContent = L.DomUtil.create('div', 'measure-area-content');
  249. var oLabelObj = L.DomUtil.create('p');
  250. var delLabel = L.DomUtil.create('div','distance-ico-del');
  251. //delLabel.innerHTML = '删除';
  252. delLabel.lC = _this._mC;
  253. oLabelObj.lC = _this._mC;
  254. L.DomEvent.on(delLabel, 'click', function(e) {
  255. L.DomEvent.stopPropagation(e);
  256. _this.del(delLabel.lC)
  257. });
  258. oLabelObj.appendChild(areaLabel);
  259. L.DomEvent.on(oLabelObj, 'dblclick', function() {
  260. L.DomEvent.stopPropagation(e);
  261. _this.del(oLabelObj.lC);
  262. });
  263. oLabelObjContent.appendChild(oLabelObj);
  264. if(_this.options.closeButton){
  265. oLabelObjContent.appendChild(delLabel);
  266. }
  267. L.marker(e.latlng, { icon: L.divIcon({ className: 'distance-div-icon' }) }).bindLabel(oLabelObjContent, { noHide: true, clickable: true, className: 'measure-distance-tip', offset: [0, 0] }).addTo(_this._measureAObjs[_this._mC]);
  268. _this.editerCSS();
  269. },
  270. /**
  271. * 修改测距样式
  272. */
  273. editerCSS: function() {
  274. var _this = this;
  275. $(".measure-area-content span").css({
  276. "color": _this.options.color,
  277. })
  278. $(".measure-area-content span").css({
  279. "font-size": _this.options.font_size,
  280. })
  281. $(".measure-area-content").css({
  282. "background": 'rgba(255,255,255,0.5)'
  283. });
  284. },
  285. /**
  286. * 合并样式
  287. */
  288. addCss: function(options) {
  289. var _this = this;
  290. _.merge(this.options, options);
  291. _this.editerCSS();
  292. },
  293. /**
  294. * 通过坐标点计算面积
  295. * @type {Function}
  296. * @returns {Number} 面积
  297. * @private
  298. */
  299. _getArea: function() {
  300. var _this = this;
  301. var latLngs = _this._measureAObjs[_this._mC].measurePoints;
  302. var pointsCount = latLngs.length,
  303. area = 0.0,
  304. d2r = Math.PI / 180,
  305. p1, p2;
  306. if (pointsCount > 2) {
  307. for (var i = 0; i < pointsCount; i++) {
  308. p1 = latLngs[i];
  309. p2 = latLngs[(i + 1) % pointsCount];
  310. area += ((p2.lng - p1.lng) * d2r) *
  311. (2 + Math.sin(p1.lat * d2r) + Math.sin(p2.lat * d2r));
  312. }
  313. area = area * 6378137.0 * 6378137.0 / 2.0;
  314. }
  315. area = Math.abs(area);
  316. if (area > 1000000) {
  317. area = (area * 0.000001).toFixed(2) + ' 平方公里';
  318. } else {
  319. area = area.toFixed(2) + ' 米&sup2;';
  320. }
  321. return area;
  322. },
  323. _removeMeasureGroup: function() {
  324. var _this = this;
  325. if(_this._map){
  326. _this._map.doubleClickZoom.enable();
  327. _this._map.off('click', _this._onClickPoint, this);
  328. }
  329. },
  330. /**
  331. * 重启测面
  332. * [_restartMearing description]
  333. * @return {[type]} [description]
  334. */
  335. _restartMearing:function(){
  336. var _this = this;
  337. _this.start();
  338. },
  339. /**
  340. * 删除对应iC的测距
  341. * @type {Function}
  342. */
  343. del: function(mC) {
  344. var _this = this;
  345. /*
  346. var event = event || window.event;
  347. L.DomEvent.stop(event);*/
  348. _this._measureGroup.removeLayer(_this._measureAObjs[mC].polygon);
  349. _this._measureGroup.removeLayer(_this._measureAObjs[mC]);
  350. delete _this._measureAObjs[mC];
  351. },
  352. });
  353. L.control.measureArea = function(options) {
  354. return new L.Control.MeasureArea(options);
  355. }
  356. /**
  357. * 测量工具
  358. */
  359. map2DViewer.setAreaToolStyle = function(options) {
  360. this.areaTool.addCss(options);
  361. }
  362. map2DViewer.areaToolFire = function(data) {};
  363. map2DViewer.areaToolDelFire = function(data) {};
  364. map2DViewer.setAreaTool = function(options) {
  365. var defaultData = {
  366. action: 'add',
  367. position: 'topleft',
  368. offset: [10, 40],
  369. background:"#fff",
  370. color:"#000",
  371. font_size:"14px",
  372. closeButton:true
  373. }
  374. _.merge(defaultData, options);
  375. switch (defaultData.action) {
  376. case 'add':
  377. this.areaTool = new L.Control.MeasureArea({
  378. position: defaultData.position,
  379. offset: defaultData.offset,
  380. background:defaultData.background,
  381. color:defaultData.color,
  382. font_size:defaultData.font_size,
  383. closeButton:defaultData.closeButton
  384. }).addTo(this.map);
  385. this.map.on('measure-area-result', map2DViewer.areaToolFire);
  386. this.map.on('measure-area-delete', map2DViewer.areaToolDelFire);
  387. this.areaTool.start();
  388. return this.areaTool;
  389. break;
  390. case 'restart':
  391. if(this.areaTool){
  392. this.areaTool._restartMearing();
  393. }
  394. break;
  395. case 'clear':
  396. if(this.areaTool){
  397. this.areaTool.cleanAllMeasure();
  398. this.areaTool._removeMeasureGroup();
  399. this.map.removeControl(this.areaTool);
  400. }
  401. break;
  402. case 'remove':
  403. if(this.areaTool){
  404. this.areaTool._removeMeasureGroup();
  405. this.map.off('measure-area-result', map2DViewer.areaToolFire);
  406. this.map.off('measure-area-delete', map2DViewer.areaToolDelFire);
  407. }
  408. break;
  409. }
  410. }