Edit.Poly.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. L.Edit = L.Edit || {};
  2. /*
  3. * L.Edit.Poly is an editing handler for polylines and polygons.
  4. */
  5. L.Edit.Poly = L.Handler.extend({
  6. options: {
  7. icon: new L.DivIcon({
  8. iconSize: new L.Point(8, 8),
  9. className: 'leaflet-div-icon leaflet-editing-icon'
  10. })
  11. },
  12. initialize: function (poly, options) {
  13. this._poly = poly;
  14. L.setOptions(this, options);
  15. },
  16. addHooks: function () {
  17. if (this._poly._map) {
  18. if (!this._markerGroup) {
  19. this._initMarkers();
  20. }
  21. this._poly._map.addLayer(this._markerGroup);
  22. }
  23. },
  24. removeHooks: function () {
  25. if (this._poly._map) {
  26. this._poly._map.removeLayer(this._markerGroup);
  27. delete this._markerGroup;
  28. delete this._markers;
  29. }
  30. },
  31. updateMarkers: function () {
  32. this._markerGroup.clearLayers();
  33. this._initMarkers();
  34. },
  35. _initMarkers: function () {
  36. if (!this._markerGroup) {
  37. this._markerGroup = new L.LayerGroup();
  38. }
  39. this._markers = [];
  40. var latlngs = this._poly._latlngs,
  41. i, j, len, marker;
  42. // TODO refactor holes implementation in Polygon to support it here
  43. if(latlngs.length>1){
  44. for (i = 0, len = latlngs.length; i < len; i++) {
  45. marker = this._createMarker(latlngs[i], i);
  46. marker.on('click', this._onMarkerClick, this);
  47. this._markers.push(marker);
  48. }
  49. }else{
  50. for (i = 0, len = latlngs[0].length; i < len; i++) {
  51. marker = this._createMarker(latlngs[0][i], i);
  52. marker.on('click', this._onMarkerClick, this);
  53. this._markers.push(marker);
  54. }
  55. }
  56. var markerLeft, markerRight;
  57. for (i = 0, j = len - 1; i < len; j = i++) {
  58. if (i === 0 && !(L.Polygon && (this._poly instanceof L.Polygon))) {
  59. continue;
  60. }
  61. markerLeft = this._markers[j];
  62. markerRight = this._markers[i];
  63. this._createMiddleMarker(markerLeft, markerRight);
  64. this._updatePrevNext(markerLeft, markerRight);
  65. }
  66. },
  67. _createMarker: function (latlng, index) {
  68. /*if(index >=0){
  69. var marker = new L.Marker(latlng[index], {
  70. draggable: true,
  71. icon: this.options.icon
  72. });
  73. }else{*/
  74. var marker = new L.Marker(latlng, {
  75. draggable: true,
  76. icon: this.options.icon
  77. });
  78. //}
  79. marker._origLatLng = latlng;
  80. marker._index = index;
  81. marker.on('drag', this._onMarkerDrag, this);
  82. marker.on('dragend', this._fireEdit, this);
  83. this._markerGroup.addLayer(marker);
  84. return marker;
  85. },
  86. _removeMarker: function (marker) {
  87. var i = marker._index;
  88. this._markerGroup.removeLayer(marker);
  89. this._markers.splice(i, 1);
  90. this._poly.spliceLatLngs(i, 1);
  91. this._updateIndexes(i, -1);
  92. marker
  93. .off('drag', this._onMarkerDrag, this)
  94. .off('dragend', this._fireEdit, this)
  95. .off('click', this._onMarkerClick, this);
  96. },
  97. _fireEdit: function () {
  98. this._poly.edited = true;
  99. this._poly.fire('edit');
  100. },
  101. _onMarkerDrag: function (e) {
  102. var marker = e.target;
  103. L.extend(marker._origLatLng, marker._latlng);
  104. if (marker._middleLeft) {
  105. marker._middleLeft.setLatLng(this._getMiddleLatLng(marker._prev, marker));
  106. }
  107. if (marker._middleRight) {
  108. marker._middleRight.setLatLng(this._getMiddleLatLng(marker, marker._next));
  109. }
  110. this._poly.redraw();
  111. },
  112. _onMarkerClick: function (e) {
  113. // we want to remove the marker on click, but if latlng count < 3, polyline would be invalid
  114. if (this._poly._latlngs.length < 3) { return; }
  115. var marker = e.target;
  116. // remove the marker
  117. this._removeMarker(marker);
  118. // update prev/next links of adjacent markers
  119. this._updatePrevNext(marker._prev, marker._next);
  120. // remove ghost markers near the removed marker
  121. if (marker._middleLeft) {
  122. this._markerGroup.removeLayer(marker._middleLeft);
  123. }
  124. if (marker._middleRight) {
  125. this._markerGroup.removeLayer(marker._middleRight);
  126. }
  127. // create a ghost marker in place of the removed one
  128. if (marker._prev && marker._next) {
  129. this._createMiddleMarker(marker._prev, marker._next);
  130. } else if (!marker._prev) {
  131. marker._next._middleLeft = null;
  132. } else if (!marker._next) {
  133. marker._prev._middleRight = null;
  134. }
  135. this._fireEdit();
  136. },
  137. _updateIndexes: function (index, delta) {
  138. this._markerGroup.eachLayer(function (marker) {
  139. if (marker._index > index) {
  140. marker._index += delta;
  141. }
  142. });
  143. },
  144. _createMiddleMarker: function (marker1, marker2) {
  145. var latlng = this._getMiddleLatLng(marker1, marker2),
  146. marker = this._createMarker(latlng),
  147. onClick,
  148. onDragStart,
  149. onDragEnd;
  150. marker.setOpacity(0.6);
  151. marker1._middleRight = marker2._middleLeft = marker;
  152. onDragStart = function () {
  153. var i = marker2._index;
  154. marker._index = i;
  155. marker
  156. .off('click', onClick, this)
  157. .on('click', this._onMarkerClick, this);
  158. latlng.lat = marker.getLatLng().lat;
  159. latlng.lng = marker.getLatLng().lng;
  160. this._poly.spliceLatLngs(i, 0, latlng);
  161. this._markers.splice(i, 0, marker);
  162. marker.setOpacity(1);
  163. this._updateIndexes(i, 1);
  164. marker2._index++;
  165. this._updatePrevNext(marker1, marker);
  166. this._updatePrevNext(marker, marker2);
  167. };
  168. onDragEnd = function () {
  169. marker.off('dragstart', onDragStart, this);
  170. marker.off('dragend', onDragEnd, this);
  171. this._createMiddleMarker(marker1, marker);
  172. this._createMiddleMarker(marker, marker2);
  173. };
  174. onClick = function () {
  175. onDragStart.call(this);
  176. onDragEnd.call(this);
  177. this._fireEdit();
  178. };
  179. marker
  180. .on('click', onClick, this)
  181. .on('dragstart', onDragStart, this)
  182. .on('dragend', onDragEnd, this);
  183. this._markerGroup.addLayer(marker);
  184. },
  185. _updatePrevNext: function (marker1, marker2) {
  186. if (marker1) {
  187. marker1._next = marker2;
  188. }
  189. if (marker2) {
  190. marker2._prev = marker1;
  191. }
  192. },
  193. _getMiddleLatLng: function (marker1, marker2) {
  194. var map = this._poly._map,
  195. p1 = map.latLngToLayerPoint(marker1.getLatLng()),
  196. p2 = map.latLngToLayerPoint(marker2.getLatLng());
  197. return map.layerPointToLatLng(p1._add(p2)._divideBy(2));
  198. }
  199. });
  200. L.Polyline.addInitHook(function () {
  201. // Check to see if handler has already been initialized. This is to support versions of Leaflet that still have L.Handler.PolyEdit
  202. if (this.editing) {
  203. return;
  204. }
  205. if (L.Edit.Poly) {
  206. this.editing = new L.Edit.Poly(this);
  207. if (this.options.editable) {
  208. this.editing.enable();
  209. }
  210. }
  211. this.on('add', function () {
  212. if (this.editing && this.editing.enabled()) {
  213. this.editing.addHooks();
  214. }
  215. });
  216. this.on('remove', function () {
  217. if (this.editing && this.editing.enabled()) {
  218. this.editing.removeHooks();
  219. }
  220. });
  221. });