mapbox-gl-draw-ellipse.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. "use strict";
  2. var doubleClickZoom = {
  3. enable: function enable(ctx) {
  4. setTimeout(function () {
  5. if (!ctx.map || !ctx.map.doubleClickZoom || !ctx._ctx || !ctx._ctx.store || !ctx._ctx.store.getInitialConfigValue) return;
  6. if (!ctx._ctx.store.getInitialConfigValue("doubleClickZoom")) return;
  7. ctx.map.doubleClickZoom.enable();
  8. }, 0);
  9. },
  10. disable: function disable(ctx) {
  11. setTimeout(function () {
  12. if (!ctx.map || !ctx.map.doubleClickZoom) return;
  13. ctx.map.doubleClickZoom.disable();
  14. }, 0);
  15. }
  16. };
  17. var DrawEllipse = {
  18. onSetup: function onSetup(opts) {
  19. this.eccentricity = opts.eccentricity >= 0 && opts.eccentricity < 1 ? opts.eccentricity : 0.8;
  20. this.divisions = opts.divisions || 60;
  21. var ellipse = this.newFeature({
  22. type: "Feature",
  23. properties: {},
  24. geometry: {
  25. type: "Polygon",
  26. coordinates: [[]]
  27. }
  28. });
  29. this.addFeature(ellipse);
  30. this.clearSelectedFeatures();
  31. doubleClickZoom.disable(this);
  32. this.updateUIClasses({mouse: "add"});
  33. this.setActionableState({
  34. trash: true
  35. });
  36. return {
  37. ellipse: ellipse
  38. };
  39. },
  40. // 支持移动端触摸
  41. onTap: function onTap(state, e) {
  42. if (state.center) this.onMouseMove(state, e);
  43. this.onClick(state, e);
  44. },
  45. // 每当用户点击地图时,Draw将调用`onClick`
  46. onClick: function onClick(state, e) {
  47. // 如果state.center存在,则表示其第二次单击
  48. // 更改为simple_select模式
  49. if (state.center && state.center[0] !== e.lngLat.lng && state.center[1] !== e.lngLat.lat) {
  50. this.updateUIClasses({mouse: "pointer"});
  51. this.changeMode("simple_select", {featuresId: state.ellipse.id});
  52. }
  53. // 在第一次单击时,保存单击的点坐标作为椭圆的中心点
  54. state.center = [e.lngLat.lng, e.lngLat.lat];
  55. },
  56. onMouseMove: function onMouseMove(state, e) {
  57. // 根据椭圆离心率e=√(1-b^2/a^2),计算出b=a√(1-e^2)
  58. if (state.center) {
  59. var xRadius = Math.sqrt(Math.pow(e.lngLat.lng - state.center[0], 2) + Math.pow(e.lngLat.lat - state.center[1], 2));
  60. var yRadius = xRadius * Math.sqrt(1 - Math.pow(this.eccentricity, 2));
  61. var radian = Math.atan2(e.lngLat.lat - state.center[1], e.lngLat.lng - state.center[0]);
  62. var twoPi = Math.PI * 2;
  63. for (var i = 0, length = this.divisions; i <= length; i++) {
  64. var t = i / length;
  65. var angle = t * twoPi;
  66. var x = state.center[0] + xRadius * Math.cos(angle);
  67. var y = state.center[1] + yRadius * Math.sin(angle);
  68. if (radian !== 0) {
  69. var cos = Math.cos(radian);
  70. var sin = Math.sin(radian);
  71. var tx = x - state.center[0];
  72. var ty = y - state.center[1];
  73. // 围绕椭圆中心旋转点。
  74. x = tx * cos - ty * sin + state.center[0];
  75. y = tx * sin + ty * cos + state.center[1];
  76. }
  77. // 更新要素坐标
  78. state.ellipse.updateCoordinate("0." + i, x, y);
  79. }
  80. }
  81. },
  82. // 每当用户在聚焦地图时点击某个键时,它将在此处发送
  83. onKeyUp: function onKeyUp(state, e) {
  84. if (e.keyCode === 27) return this.changeMode("simple_select");
  85. },
  86. onStop: function onStop(state) {
  87. doubleClickZoom.enable(this);
  88. this.updateUIClasses({mouse: "none"});
  89. this.activateUIButton();
  90. // 检查我们是否删除了此要素
  91. if (this.getFeature(state.ellipse.id) === undefined) return;
  92. if (state.ellipse.isValid()) {
  93. this.map.fire("draw.create", {
  94. features: [state.ellipse.toGeoJSON()]
  95. });
  96. } else {
  97. this.deleteFeature([state.ellipse.id], {silent: true});
  98. this.changeMode("simple_select", {}, {silent: true});
  99. }
  100. },
  101. toDisplayFeatures: function toDisplayFeatures(state, geojson, display) {
  102. var isActivePolygon = geojson.properties.id === state.ellipse.id;
  103. geojson.properties.active = isActivePolygon ? "true" : "false";
  104. if (!isActivePolygon) return display(geojson);
  105. if (!state.center) return;
  106. return display(geojson);
  107. },
  108. onTrash: function onTrash(state) {
  109. this.deleteFeature([state.ellipse.id], {silent: true});
  110. this.changeMode("simple_select");
  111. }
  112. };