@mapgis/mapbox-gl-draw-radius 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mapgis/mapbox-gl-draw-radius",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "",
5
5
  "main": "dist/radius-mode.min.js",
6
6
  "module": "src/radius-mode.js",
@@ -11,6 +11,7 @@ import MapboxDraw from "@mapbox/mapbox-gl-draw";
11
11
  import numeral from "numeral";
12
12
  import _ from "lodash";
13
13
  import lineDistance from "@turf/length";
14
+ import * as turf from "@turf/turf";
14
15
 
15
16
  const RadiusMode = _.extend({}, MapboxDraw.modes.draw_line_string);
16
17
 
@@ -21,51 +22,72 @@ function createVertex(parentId, coordinates, path, selected) {
21
22
  meta: "vertex",
22
23
  parent: parentId,
23
24
  coord_path: path,
24
- active: selected ? "true" : "false"
25
+ active: selected ? "true" : "false",
25
26
  },
26
27
  geometry: {
27
28
  type: "Point",
28
- coordinates
29
- }
29
+ coordinates,
30
+ },
30
31
  };
31
32
  }
32
33
 
33
34
  // create a circle-like polygon given a center point and radius
34
35
  // https://stackoverflow.com/questions/37599561/drawing-a-circle-with-the-radius-in-miles-meters-with-mapbox-gl-js/39006388#39006388
35
- function createGeoJSONCircle(center, radiusInKm, parentId, points = 64) {
36
- const coords = {
37
- latitude: center[1],
38
- longitude: center[0]
39
- };
40
-
41
- const km = radiusInKm;
42
-
43
- const ret = [];
44
- const distanceX = km / 111.32;
45
- const distanceY = km / 110.574;
46
-
47
- let theta;
48
- let x;
49
- let y;
50
- for (let i = 0; i < points; i += 1) {
51
- theta = (i / points) * (2 * Math.PI);
52
- x = distanceX * Math.cos(theta);
53
- y = distanceY * Math.sin(theta);
54
-
55
- ret.push([coords.longitude + x, coords.latitude + y]);
56
- }
57
- ret.push(ret[0]);
58
-
59
- return {
60
- type: "Feature",
61
- geometry: {
62
- type: "Polygon",
63
- coordinates: [ret]
64
- },
65
- properties: {
66
- parent: parentId
36
+ function createGeoJSONCircle(
37
+ center,
38
+ radiusInKm,
39
+ parentId,
40
+ epsgCode,
41
+ points = 64
42
+ ) {
43
+ if (epsgCode.includes("4326")) {
44
+ // 经纬度坐标系下绘制圆
45
+ const coords = {
46
+ latitude: center[1],
47
+ longitude: center[0],
48
+ };
49
+
50
+ const km = radiusInKm;
51
+
52
+ const ret = [];
53
+ // const distanceX = km / 111.32;
54
+ // const distanceY = km / 110.574;
55
+ const distanceX =
56
+ km / (111.32 * Math.cos((coords.latitude * Math.PI) / 180));
57
+ const distanceY = km / 110.574;
58
+
59
+ let theta;
60
+ let x;
61
+ let y;
62
+ for (let i = 0; i < points; i += 1) {
63
+ theta = (i / points) * (2 * Math.PI);
64
+ x = distanceX * Math.cos(theta);
65
+ y = distanceY * Math.sin(theta);
66
+
67
+ ret.push([coords.longitude + x, coords.latitude + y]);
67
68
  }
68
- };
69
+ ret.push(ret[0]);
70
+ return {
71
+ type: "Feature",
72
+ geometry: {
73
+ type: "Polygon",
74
+ coordinates: [ret],
75
+ },
76
+ properties: {
77
+ parent: parentId,
78
+ },
79
+ };
80
+ } else {
81
+ // 墨卡托坐标系下绘制圆
82
+ const options = {
83
+ steps: 64,
84
+ units: "kilometers",
85
+ properties: { parent: parentId },
86
+ };
87
+ const circle = turf.circle(center, radiusInKm, options);
88
+
89
+ return circle;
90
+ }
69
91
  }
70
92
 
71
93
  function getDisplayMeasurements(feature) {
@@ -102,14 +124,14 @@ function getDisplayMeasurements(feature) {
102
124
  metric: `${numeral(metricMeasurement).format(metricFormat)} ${metricUnits}`,
103
125
  standard: `${numeral(standardMeasurement).format(
104
126
  standardFormat
105
- )} ${standardUnits}`
127
+ )} ${standardUnits}`,
106
128
  };
107
129
 
108
130
  return displayMeasurements;
109
131
  }
110
132
 
111
133
  const doubleClickZoom = {
112
- enable: ctx => {
134
+ enable: (ctx) => {
113
135
  setTimeout(() => {
114
136
  // First check we've got a map and some context.
115
137
  if (
@@ -124,29 +146,29 @@ const doubleClickZoom = {
124
146
  if (!ctx._ctx.store.getInitialConfigValue("doubleClickZoom")) return;
125
147
  ctx.map.doubleClickZoom.enable();
126
148
  }, 0);
127
- }
149
+ },
128
150
  };
129
- RadiusMode.onSetup = function(opts) {
151
+ RadiusMode.onSetup = function (opts) {
130
152
  const props = MapboxDraw.modes.draw_line_string.onSetup.call(this, opts);
131
153
  const circle = this.newFeature({
132
154
  type: "Feature",
133
155
  properties: {
134
- meta: "radius"
156
+ meta: "radius",
135
157
  },
136
158
  geometry: {
137
159
  type: "Polygon",
138
- coordinates: [[]]
139
- }
160
+ coordinates: [[]],
161
+ },
140
162
  });
141
163
  this.addFeature(circle);
142
164
 
143
165
  return {
144
166
  ...props,
145
- circle
167
+ circle,
146
168
  };
147
169
  };
148
170
 
149
- RadiusMode.clickAnywhere = function(state, e) {
171
+ RadiusMode.clickAnywhere = function (state, e) {
150
172
  // this ends the drawing after the user creates a second point, triggering this.onStop
151
173
  if (state.currentVertexPosition === 1) {
152
174
  state.line.addCoordinate(0, e.lngLat.lng, e.lngLat.lat);
@@ -172,19 +194,26 @@ RadiusMode.clickAnywhere = function(state, e) {
172
194
  return null;
173
195
  };
174
196
 
175
- RadiusMode.onMouseMove = function(state, e) {
197
+ RadiusMode.onMouseMove = function (state, e) {
176
198
  MapboxDraw.modes.draw_line_string.onMouseMove.call(this, state, e);
177
199
  const geojson = state.line.toGeoJSON();
178
200
  const center = geojson.geometry.coordinates[0];
179
201
  const radiusInKm = lineDistance(geojson, "kilometers");
180
- const circleFeature = createGeoJSONCircle(center, radiusInKm, state.line.id);
202
+ const epsgCode =
203
+ this.map && this.map.crs ? this.map.crs.epsgCode : "EPSG:4326";
204
+ const circleFeature = createGeoJSONCircle(
205
+ center,
206
+ radiusInKm,
207
+ state.line.id,
208
+ epsgCode
209
+ );
181
210
  circleFeature.properties.meta = "radius";
182
211
  state.circle.setCoordinates(circleFeature.geometry.coordinates);
183
212
  };
184
213
 
185
214
  // creates the final geojson point feature with a radius property
186
215
  // triggers draw.create
187
- RadiusMode.onStop = function(state) {
216
+ RadiusMode.onStop = function (state) {
188
217
  doubleClickZoom.enable(this);
189
218
 
190
219
  this.activateUIButton();
@@ -199,7 +228,7 @@ RadiusMode.onStop = function(state) {
199
228
  this.deleteFeature([state.line.id], { silent: true });
200
229
 
201
230
  this.map.fire("draw.create", {
202
- features: [state.circle.toGeoJSON()]
231
+ features: [state.circle.toGeoJSON()],
203
232
  });
204
233
  } else {
205
234
  this.deleteFeature([state.line.id], { silent: true });
@@ -207,7 +236,7 @@ RadiusMode.onStop = function(state) {
207
236
  }
208
237
  };
209
238
 
210
- RadiusMode.toDisplayFeatures = function(state, geojson, display) {
239
+ RadiusMode.toDisplayFeatures = function (state, geojson, display) {
211
240
  const isActiveLine = geojson.properties.id === state.line.id;
212
241
  geojson.properties.active = isActiveLine ? "true" : "false";
213
242
  if (!isActiveLine) return display(geojson);
@@ -246,12 +275,12 @@ RadiusMode.toDisplayFeatures = function(state, geojson, display) {
246
275
  meta: "currentPosition",
247
276
  radiusMetric: displayMeasurements.metric,
248
277
  radiusStandard: displayMeasurements.standard,
249
- parent: state.line.id
278
+ parent: state.line.id,
250
279
  },
251
280
  geometry: {
252
281
  type: "Point",
253
- coordinates: geojson.geometry.coordinates[1]
254
- }
282
+ coordinates: geojson.geometry.coordinates[1],
283
+ },
255
284
  };
256
285
  display(currentVertex);
257
286