mapbox-gl-draw-cirle.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. var CircleMode = {};
  2. var origon;
  3. var snapAngle;
  4. var angle;
  5. var sides;
  6. var destination;
  7. var id;
  8. // When the mode starts this function will be called.
  9. // The `opts` argument comes from `draw.changeMode('lotsofpoints', {count:7})`.
  10. // The value returned should be an object and will be passed to all other lifecycle functions
  11. CircleMode.onSetup = function (opts) {
  12. var state = {};
  13. destination = {};
  14. origon = null;
  15. sides = opts.sides || 40;
  16. if (sides < 40) {
  17. sides = 40;
  18. }
  19. var polygon = this.newFeature({
  20. 'type': 'Feature',
  21. 'geometry': {
  22. 'type': 'Polygon',
  23. 'coordinates': [[]]
  24. },
  25. "properties": {
  26. //sides: state.sides
  27. }
  28. });
  29. //sides = state.sides?state.sides:40;
  30. this.addFeature(polygon);
  31. this.clearSelectedFeatures();
  32. //doubleClickZoom.disable(this);
  33. this.updateUIClasses({ mouse: 'add' });
  34. this.activateUIButton('polygon');
  35. this.setActionableState({
  36. trash: true
  37. });
  38. return {
  39. polygon: polygon,
  40. id: polygon,
  41. currentVertexPosition: 0
  42. };
  43. };
  44. CircleMode.onClick = function (state, e) {
  45. origon = { x: e.lngLat.lng, y: e.lngLat.lat };
  46. if (state.currentVertexPosition > 0 && destination && destination.x == origon.x && destination.y == origon.y) {
  47. this.map.fire("draw.create", {
  48. features: [state.polygon.toGeoJSON()]
  49. });
  50. return this.changeMode('simple_select', { featureIds: [state.polygon.id] });
  51. }
  52. var radius = 0.0439453125;
  53. angle = Math.PI * (1 / sides - 1 / 2);
  54. if (snapAngle) {
  55. angle += snapAngle * (Math.PI / 180)
  56. }
  57. var feature = getcircle(origon, radius, sides, snapAngle);
  58. this.updateUIClasses({ mouse: 'add' });
  59. this.deleteFeature([state.id], { silent: true });
  60. state.currentVertexPosition++;
  61. state.polygon.coordinates = [feature];
  62. this.addFeature(state.polygon);
  63. };
  64. CircleMode.onMouseMove = function (state, e) {
  65. if (origon) {
  66. destination = { x: e.lngLat.lng, y: e.lngLat.lat };
  67. calculateAngle(destination);
  68. var radius = distanceTo(destination);
  69. // var value = getGreatCircleDistance(origon[1], origon[0], destination[1], destination[0]);
  70. // map.setPaintProperty('measure-points', 'circle-radius', parseFloat(value));
  71. var feature = getcircle(origon, radius, sides, snapAngle);
  72. this.deleteFeature([id], { silent: true });
  73. state.polygon.coordinates = [feature];
  74. this.addFeature(state.polygon);
  75. }
  76. };
  77. // Whenever a user clicks on a key while focused on the map, it will be sent here
  78. CircleMode.onKeyUp = function (state, e) {
  79. if (e.keyCode === 27) return this.changeMode('simple_select');
  80. };
  81. // This is the only required function for a mode.
  82. // It decides which features currently in Draw's data store will be rendered on the map.
  83. // All features passed to `display` will be rendered, so you can pass multiple display features per internal feature.
  84. // See `styling-draw` in `API.md` for advice on making display features
  85. CircleMode.toDisplayFeatures = function (state, geojson, display) {
  86. display(geojson);
  87. };
  88. CircleMode.onTrash = function (state) {
  89. this.deleteFeature([state.polygon.id], { silent: true });
  90. this.changeMode('simple_select');
  91. };
  92. function calculateAngle(point, evt) {
  93. var alpha = Math.atan2(point.y - origon.y, point.x - origon.x);
  94. if (snapAngle && this.snapToggle && !evt[this.snapToggle]) {
  95. var snapAngleRad = Math.PI / 180 * snapAngle;
  96. angle = Math.round(alpha / snapAngleRad) * snapAngleRad
  97. } else {
  98. angle = alpha
  99. }
  100. }
  101. function distanceTo(destination, options) {
  102. var edge = !(options && options.edge === false);
  103. var details = edge && options && options.details;
  104. var distance, x0, y0, x1, y1, result;
  105. x0 = origon.x;
  106. y0 = origon.y;
  107. x1 = destination.x;
  108. y1 = destination.y;
  109. distance = Math.sqrt(Math.pow(x0 - x1, 2) + Math.pow(y0 - y1, 2));
  110. result = !details ? distance : { x0: x0, y0: y0, x1: x1, y1: y1, distance: distance }
  111. return result
  112. }
  113. function getcircle(origin, radius, sides, rotation) {
  114. var angle = Math.PI * (1 / sides - 1 / 2);
  115. if (rotation) {
  116. angle += rotation / 180 * Math.PI
  117. }
  118. var rotatedAngle, x, y;
  119. var points = [];
  120. for (var i = 0; i < sides; ++i) {
  121. rotatedAngle = angle + i * 2 * Math.PI / sides;
  122. x = origin.x + radius * Math.cos(rotatedAngle);
  123. y = origin.y + radius * Math.sin(rotatedAngle);
  124. points.push([x, y])
  125. }
  126. return points;
  127. }