@smart100/spu-web-plugin 1.0.8 → 1.0.9
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/dist/index.d.ts +9 -0
- package/dist/spu-web-plugin.mjs +1335 -367
- package/package.json +1 -1
- package/src/index.ts +4 -2
- package/src/login.ts +5 -43
- package/src/map/AMapKey.ts +31 -0
- package/src/map/AMapLoader.ts +43 -0
- package/src/map/MapService.ts +167 -0
- package/src/map/index.ts +564 -0
- package/src/map/utils.ts +98 -0
- package/src/tenantSetting.ts +88 -0
- package/src/types/global.d.ts +0 -4
- package/src/types/index.d.ts +9 -0
- package/src/types/shims-lib.d.ts +14 -3
- package/src/utils.ts +41 -1
- package/src/AMapLoader.ts +0 -46
- package/src/location.ts +0 -208
package/src/map/index.ts
ADDED
|
@@ -0,0 +1,564 @@
|
|
|
1
|
+
import { urlquery } from '../urlquery'
|
|
2
|
+
import { cloneDeep } from 'lodash-es'
|
|
3
|
+
import { mapService } from './MapService'
|
|
4
|
+
import { getAMapKey } from './AMapKey'
|
|
5
|
+
import { axios } from '../axios'
|
|
6
|
+
import { wgs84ToGcj02, BMapTransformBD09ToGCJ02Points } from './utils'
|
|
7
|
+
|
|
8
|
+
type Location = {
|
|
9
|
+
longitude: string
|
|
10
|
+
latitude: string
|
|
11
|
+
address?: string
|
|
12
|
+
// [propName: string]: any;
|
|
13
|
+
} | null
|
|
14
|
+
|
|
15
|
+
const cachetime = 30000 // 缓存时间30秒
|
|
16
|
+
let datetime: number | null = null
|
|
17
|
+
let lastLocation: Location = null
|
|
18
|
+
let runing = false
|
|
19
|
+
let locationPromise: Promise<Location>
|
|
20
|
+
|
|
21
|
+
// app端默认坐标为 gcj02
|
|
22
|
+
const getLocationByNative = async (): Promise<Location> => {
|
|
23
|
+
console.log('getLocationByNative start...')
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
let isload = false
|
|
26
|
+
setTimeout(() => {
|
|
27
|
+
if (!isload) {
|
|
28
|
+
console.error('getLocationByNative fail: timeout 30000')
|
|
29
|
+
resolve(null)
|
|
30
|
+
}
|
|
31
|
+
}, 30000)
|
|
32
|
+
window.Native.getLocation((res: any, error: any, status: any) => {
|
|
33
|
+
// console.log('getLocation res', res)
|
|
34
|
+
// console.log('getLocation error', error)
|
|
35
|
+
// console.log('getLocation status', status)
|
|
36
|
+
isload = true
|
|
37
|
+
if (res && res?.longitude && res?.latitude) {
|
|
38
|
+
const result = {
|
|
39
|
+
longitude: res.longitude.toString(),
|
|
40
|
+
latitude: res.latitude.toString(),
|
|
41
|
+
address: res.address || ''
|
|
42
|
+
}
|
|
43
|
+
console.log(`getLocationByNative success: ${JSON.stringify(result)}`)
|
|
44
|
+
resolve(result)
|
|
45
|
+
} else {
|
|
46
|
+
console.error('getLocationByNative fail')
|
|
47
|
+
resolve(null)
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 浏览器定位: 需要开启https
|
|
54
|
+
const getLocationByNavigator = async (): Promise<Location> => {
|
|
55
|
+
console.log('getLocationByNavigator start...')
|
|
56
|
+
return new Promise((resolve, reject) => {
|
|
57
|
+
if ('geolocation' in navigator) {
|
|
58
|
+
const time = setTimeout(() => {
|
|
59
|
+
console.error('getLocationByNavigator fail: timeout 5000')
|
|
60
|
+
resolve(null)
|
|
61
|
+
}, 5000)
|
|
62
|
+
navigator.geolocation.getCurrentPosition(
|
|
63
|
+
(position) => {
|
|
64
|
+
// console.log(position)
|
|
65
|
+
// debugger
|
|
66
|
+
clearTimeout(time)
|
|
67
|
+
if (position.coords) {
|
|
68
|
+
// 浏览器定位默认返回 WGS84 坐标 需要转化为 GCJ02 坐标
|
|
69
|
+
const Gcj02 = wgs84ToGcj02(position.coords.longitude, position.coords.latitude)
|
|
70
|
+
// console.log(Gcj02)
|
|
71
|
+
// debugger
|
|
72
|
+
const result = {
|
|
73
|
+
latitude: Gcj02.lat.toString(),
|
|
74
|
+
longitude: Gcj02.lng.toString()
|
|
75
|
+
}
|
|
76
|
+
console.log(`getLocationByNavigator success: ${JSON.stringify(result)}`)
|
|
77
|
+
resolve(result)
|
|
78
|
+
} else {
|
|
79
|
+
console.error('getLocationByNavigator fail')
|
|
80
|
+
resolve(null)
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
() => {
|
|
84
|
+
clearTimeout(time)
|
|
85
|
+
console.error('getLocationByNavigator fail')
|
|
86
|
+
resolve(null)
|
|
87
|
+
}
|
|
88
|
+
)
|
|
89
|
+
} else {
|
|
90
|
+
console.error('getLocationByNavigator fail: navigator.geolocation not support')
|
|
91
|
+
resolve(null)
|
|
92
|
+
}
|
|
93
|
+
})
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// ipaas ip 定位
|
|
97
|
+
const getIPLocationByIpaas = async (
|
|
98
|
+
ip?: string
|
|
99
|
+
): Promise<Location> => {
|
|
100
|
+
console.log('getIPLocationByIpaas start...')
|
|
101
|
+
return new Promise((resolve, reject) => {
|
|
102
|
+
const AMapKey = getAMapKey()
|
|
103
|
+
|
|
104
|
+
axios.post(
|
|
105
|
+
'https://silkroad.wxchina.com/api/openapi/publishEvent?topic=xw-listener&subtopic=xw-listener&apicaseid=6684389338001815271',
|
|
106
|
+
{
|
|
107
|
+
key: AMapKey.key, // 好像不传也没问题 因为key是在ipaas那边设置的
|
|
108
|
+
ip: ip || ''
|
|
109
|
+
}
|
|
110
|
+
)
|
|
111
|
+
.then((res: any) => {
|
|
112
|
+
// console.log(res)
|
|
113
|
+
// debugger
|
|
114
|
+
|
|
115
|
+
// res.data.rectangle = '113.1017375,22.93212254;113.6770499,23.3809537'
|
|
116
|
+
if (res.data.rectangle) {
|
|
117
|
+
const rectangle = res.data.rectangle
|
|
118
|
+
const rects = rectangle.split(';').map((rect: any) => {
|
|
119
|
+
const [longitude, latitude] = rect.split(',')
|
|
120
|
+
return {
|
|
121
|
+
longitude: Number(longitude),
|
|
122
|
+
latitude: Number(latitude)
|
|
123
|
+
}
|
|
124
|
+
})
|
|
125
|
+
|
|
126
|
+
const result = {
|
|
127
|
+
longitude: ((rects[0].longitude + rects[1].longitude) / 2).toString(),
|
|
128
|
+
latitude: ((rects[0].latitude + rects[1].latitude) / 2).toString()
|
|
129
|
+
}
|
|
130
|
+
console.log(`getIPLocationByIpaas success: ${JSON.stringify(result)}`)
|
|
131
|
+
resolve(result)
|
|
132
|
+
} else {
|
|
133
|
+
console.error('getIPLocationByIpaas fail')
|
|
134
|
+
resolve(null)
|
|
135
|
+
}
|
|
136
|
+
}).catch((err: any) => {
|
|
137
|
+
console.error(err)
|
|
138
|
+
console.error('getIPLocationByIpaas fail')
|
|
139
|
+
resolve(null)
|
|
140
|
+
})
|
|
141
|
+
})
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// ipaas 逆地址解析
|
|
145
|
+
const getAddressByIpaas = async (position: Location): Promise<string> => {
|
|
146
|
+
console.log('getAddressByIpaas start...')
|
|
147
|
+
// 如果不设置安全秘钥的话 js-api的逆地址查询不成功 返回 INVALID_USER_SCODE 改成用ipaas服务查询
|
|
148
|
+
return new Promise(async (resolve, reject) => {
|
|
149
|
+
if (position) {
|
|
150
|
+
try {
|
|
151
|
+
const AMapKey = getAMapKey()
|
|
152
|
+
const result = await axios.post('https://silkroad.wxchina.com/api/openapi/publishEvent?topic=xw-listener&subtopic=xw-listener&apicaseid=6684389338001809906', {
|
|
153
|
+
longitude: position.longitude,
|
|
154
|
+
latitude: position.latitude,
|
|
155
|
+
key: AMapKey.key
|
|
156
|
+
// extensions: 'all'
|
|
157
|
+
})
|
|
158
|
+
// console.log(result)
|
|
159
|
+
const address = result?.data?.formatted_address
|
|
160
|
+
if (address) {
|
|
161
|
+
console.log(`getAddressByIpaas success: ${address}`)
|
|
162
|
+
resolve(address)
|
|
163
|
+
} else {
|
|
164
|
+
console.error('getAddressByIpaas fail')
|
|
165
|
+
resolve('')
|
|
166
|
+
}
|
|
167
|
+
} catch (error) {
|
|
168
|
+
console.error(error)
|
|
169
|
+
console.error('getAddressByIpaas fail')
|
|
170
|
+
resolve('')
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
})
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// 高德定位
|
|
177
|
+
const getLocationByAmap = async (): Promise<Location> => {
|
|
178
|
+
console.log('getLocationByAmap start...')
|
|
179
|
+
return new Promise((resolve, reject) => {
|
|
180
|
+
const geolocation = new window.AMap.Geolocation({
|
|
181
|
+
enableHighAccuracy: true,
|
|
182
|
+
timeout: 15000
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
geolocation.getCurrentPosition((status: string, res: any) => {
|
|
186
|
+
// console.log(status, result)
|
|
187
|
+
// debugger
|
|
188
|
+
if (status === 'complete') {
|
|
189
|
+
const { lng, lat } = res.position
|
|
190
|
+
const result = {
|
|
191
|
+
longitude: lng.toString(),
|
|
192
|
+
latitude: lat.toString()
|
|
193
|
+
}
|
|
194
|
+
console.log(`getLocationByAmap success: ${JSON.stringify(result)}`)
|
|
195
|
+
resolve(result)
|
|
196
|
+
} else {
|
|
197
|
+
console.error('getLocationByAmap fail')
|
|
198
|
+
resolve(null)
|
|
199
|
+
}
|
|
200
|
+
})
|
|
201
|
+
})
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// 高德城市定位
|
|
205
|
+
const getCityLocationByAmap = async (): Promise<Location> => {
|
|
206
|
+
console.log('getCityLocationByAmap start...')
|
|
207
|
+
return new Promise((resolve, reject) => {
|
|
208
|
+
const geolocation = new window.AMap.Geolocation({
|
|
209
|
+
enableHighAccuracy: true,
|
|
210
|
+
timeout: 15000
|
|
211
|
+
})
|
|
212
|
+
geolocation.getCityInfo((status: string, res: any) => {
|
|
213
|
+
// console.log(res)
|
|
214
|
+
// debugger
|
|
215
|
+
if (status === 'complete') {
|
|
216
|
+
const lng = res.position[0].toString()
|
|
217
|
+
const lat = res.position[1].toString()
|
|
218
|
+
const result = {
|
|
219
|
+
longitude: lng.toString(),
|
|
220
|
+
latitude: lat.toString()
|
|
221
|
+
}
|
|
222
|
+
console.log(`getCityLocationByAmap success: ${JSON.stringify(result)}`)
|
|
223
|
+
resolve(result)
|
|
224
|
+
} else {
|
|
225
|
+
console.error('getCityLocationByAmap fail')
|
|
226
|
+
resolve(null)
|
|
227
|
+
}
|
|
228
|
+
})
|
|
229
|
+
})
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// 高德逆地址解析
|
|
233
|
+
const getAddressByAmap = async (position: Location): Promise<string> => {
|
|
234
|
+
console.log('getAddressByAmap start...')
|
|
235
|
+
console.log('getAddressByAmap changeto getAddressByIpaas')
|
|
236
|
+
// return new Promise((resolve, reject) => {
|
|
237
|
+
// if (position) {
|
|
238
|
+
// new window.AMap.Geocoder({
|
|
239
|
+
// city: '',
|
|
240
|
+
// radius: 500
|
|
241
|
+
// }).getAddress([position.longitude, position.latitude], (status: string, result: any) => {
|
|
242
|
+
// if (status === 'complete' && result.info === 'OK' && result.regeocode) {
|
|
243
|
+
// resolve(result?.regeocode?.formattedAddress || '')
|
|
244
|
+
// } else {
|
|
245
|
+
// console.error('getAddressByAmap fail')
|
|
246
|
+
// resolve('')
|
|
247
|
+
// }
|
|
248
|
+
// })
|
|
249
|
+
// }
|
|
250
|
+
// })
|
|
251
|
+
// 如果不设置安全秘钥的话 js-api的逆地址查询不成功 返回 INVALID_USER_SCODE 改成用ipaas服务查询
|
|
252
|
+
const address = await getAddressByIpaas(position)
|
|
253
|
+
return address
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// 腾讯ip定位:通过终端设备IP地址获取其当前所在地理位置,精确到市级,常用于显示当地城市天气预报、初始化用户城市等非精确定位场景。
|
|
257
|
+
const getIPLocationByTMap = async (ip?: string): Promise<Location> => {
|
|
258
|
+
console.log('getIPLocationByTMap start...')
|
|
259
|
+
return new Promise((resolve, reject) => {
|
|
260
|
+
const ipLocation = new window.TMap.service.IPLocation()
|
|
261
|
+
const params = ip ? { ip } : {}
|
|
262
|
+
ipLocation
|
|
263
|
+
.locate(params)
|
|
264
|
+
.then((res: any) => {
|
|
265
|
+
const result = {
|
|
266
|
+
longitude: res.result.location.lng.toString(),
|
|
267
|
+
latitude: res.result.location.lat.toString()
|
|
268
|
+
}
|
|
269
|
+
console.log(`getIPLocationByTMap success: ${JSON.stringify(result)}`)
|
|
270
|
+
resolve(result)
|
|
271
|
+
})
|
|
272
|
+
.catch((err: any) => {
|
|
273
|
+
console.error(err)
|
|
274
|
+
console.error(`getIPLocationByTMap fail: ${JSON.stringify(err)}`)
|
|
275
|
+
resolve(null)
|
|
276
|
+
})
|
|
277
|
+
})
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// 腾讯逆地址解析
|
|
281
|
+
const getAddressByTMap = async (position: Location): Promise<string> => {
|
|
282
|
+
console.log('getAddressByTMap start...')
|
|
283
|
+
return new Promise((resolve, reject) => {
|
|
284
|
+
if (position) {
|
|
285
|
+
const location = new window.TMap.LatLng(position.latitude, position.longitude)
|
|
286
|
+
// console.log(position)
|
|
287
|
+
// console.log(location)
|
|
288
|
+
// debugger
|
|
289
|
+
new window.TMap.service.Geocoder()
|
|
290
|
+
.getAddress({
|
|
291
|
+
location,
|
|
292
|
+
getPoi: false
|
|
293
|
+
})
|
|
294
|
+
.then((res: any) => {
|
|
295
|
+
// console.log(res)
|
|
296
|
+
// debugger
|
|
297
|
+
const address = res?.result?.formatted_addresses?.recommend || res?.result?.address
|
|
298
|
+
console.log(`getAddressByTMap success: ${address}`)
|
|
299
|
+
resolve(address)
|
|
300
|
+
})
|
|
301
|
+
.catch((err: any) => {
|
|
302
|
+
console.error(err)
|
|
303
|
+
console.error(`getAddressByTMap fail: ${JSON.stringify(err)}`)
|
|
304
|
+
resolve('')
|
|
305
|
+
})
|
|
306
|
+
}
|
|
307
|
+
})
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// 百度浏览器定位
|
|
311
|
+
const getLocationByBMap = async (): Promise<Location> => {
|
|
312
|
+
console.log('getLocationByBMap start...')
|
|
313
|
+
return new Promise((resolve, reject) => {
|
|
314
|
+
new window.BMap.Geolocation().getCurrentPosition(
|
|
315
|
+
async (res: any) => {
|
|
316
|
+
// console.log(res)
|
|
317
|
+
// debugger
|
|
318
|
+
if (!res) {
|
|
319
|
+
console.error('getLocationByBMap fail')
|
|
320
|
+
resolve(null)
|
|
321
|
+
return
|
|
322
|
+
}
|
|
323
|
+
// 初始化已经指定 window.BMap.coordType = 'BMAP_COORD_GCJ02' 定位返回的定位信息,外层[latitude,longitude]依然是BD09,然后point里面的是GCJ02
|
|
324
|
+
// {
|
|
325
|
+
// "accuracy": 150,
|
|
326
|
+
// "altitude": null,
|
|
327
|
+
// "altitudeAccuracy": null,
|
|
328
|
+
// "heading": null,
|
|
329
|
+
// "latitude": 39.915018933989,
|
|
330
|
+
// "longitude": 116.40383261074,
|
|
331
|
+
// "speed": null,
|
|
332
|
+
// "timestamp": null,
|
|
333
|
+
// "point": {
|
|
334
|
+
// "lng": 116.39745977716758,
|
|
335
|
+
// "lat": 39.908676092571405
|
|
336
|
+
// },
|
|
337
|
+
// "address": {
|
|
338
|
+
// "country": "",
|
|
339
|
+
// "city": "北京市",
|
|
340
|
+
// "city_code": 0,
|
|
341
|
+
// "district": "东城区",
|
|
342
|
+
// "province": "北京市",
|
|
343
|
+
// "street": "东华门大街",
|
|
344
|
+
// "street_number": "66号"
|
|
345
|
+
// }
|
|
346
|
+
// }
|
|
347
|
+
|
|
348
|
+
// 不用转换
|
|
349
|
+
// const point: any = await BMapTransformBD09ToGCJ02Points([{
|
|
350
|
+
// lng: res.longitude,
|
|
351
|
+
// lat: res.latitude
|
|
352
|
+
// }])
|
|
353
|
+
// console.log(point)
|
|
354
|
+
// debugger
|
|
355
|
+
|
|
356
|
+
const lng = res.point.lng.toString()
|
|
357
|
+
const lat = res.point.lat.toString()
|
|
358
|
+
const result = {
|
|
359
|
+
longitude: lng,
|
|
360
|
+
latitude: lat
|
|
361
|
+
}
|
|
362
|
+
console.log(`getLocationByBMap success: ${JSON.stringify(result)}`)
|
|
363
|
+
resolve(result)
|
|
364
|
+
},
|
|
365
|
+
{
|
|
366
|
+
enableHighAccuracy: true
|
|
367
|
+
}
|
|
368
|
+
)
|
|
369
|
+
})
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// 百度城市定位
|
|
373
|
+
const getCityLocationByBMap = async (): Promise<Location> => {
|
|
374
|
+
console.log('getCityLocationByBMap start...')
|
|
375
|
+
return new Promise((resolve, reject) => {
|
|
376
|
+
new window.BMap.LocalCity().get(async (res: any) => {
|
|
377
|
+
// console.log(res)
|
|
378
|
+
// debugger
|
|
379
|
+
const lng = res.center.lng.toString()
|
|
380
|
+
const lat = res.center.lat.toString()
|
|
381
|
+
if (lng && lat) {
|
|
382
|
+
// 城市ip定位返回的是 BD09 地址 需要转换
|
|
383
|
+
const point: any = await BMapTransformBD09ToGCJ02Points([
|
|
384
|
+
{
|
|
385
|
+
lng,
|
|
386
|
+
lat
|
|
387
|
+
}
|
|
388
|
+
])
|
|
389
|
+
// console.log(point)
|
|
390
|
+
// debugger
|
|
391
|
+
const result = {
|
|
392
|
+
longitude: point[0].lng,
|
|
393
|
+
latitude: point[0].lat
|
|
394
|
+
}
|
|
395
|
+
console.log(`getCityLocationByBMap success: ${JSON.stringify(result)}`)
|
|
396
|
+
resolve(result)
|
|
397
|
+
} else {
|
|
398
|
+
console.error('getCityLocationByBMap fail')
|
|
399
|
+
resolve(null)
|
|
400
|
+
}
|
|
401
|
+
})
|
|
402
|
+
})
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// 百度逆地址解析
|
|
406
|
+
const getAddressByBmap = async (position: Location): Promise<string> => {
|
|
407
|
+
console.log('getAddressByBmap start...')
|
|
408
|
+
return new Promise(async (resolve, reject) => {
|
|
409
|
+
// resolve('')
|
|
410
|
+
if (!position) {
|
|
411
|
+
console.error('getAddressByBmap fail')
|
|
412
|
+
resolve('')
|
|
413
|
+
return
|
|
414
|
+
}
|
|
415
|
+
// // 把 GCJ02 转化为百度 BD09 地址
|
|
416
|
+
// const points: any = await transformGCJ02ToBD09Points([{
|
|
417
|
+
// lng: position.longitude,
|
|
418
|
+
// lat: position.latitude
|
|
419
|
+
// }])
|
|
420
|
+
// const point = points[0]
|
|
421
|
+
|
|
422
|
+
// 指定了 window.BMap.coordType = 'BMAP_COORD_GCJ02' 不需要转换
|
|
423
|
+
const point = new window.BMap.Point(position.longitude, position.latitude)
|
|
424
|
+
// console.log(point)
|
|
425
|
+
// debugger
|
|
426
|
+
new window.BMap.Geocoder().getLocation(point, (result: any) => {
|
|
427
|
+
// console.log(result)
|
|
428
|
+
const address = result?.address
|
|
429
|
+
if (address) {
|
|
430
|
+
console.log(`getAddressByBmap success: ${address}`)
|
|
431
|
+
resolve(address)
|
|
432
|
+
} else {
|
|
433
|
+
console.error('getAddressByBmap fail')
|
|
434
|
+
resolve('')
|
|
435
|
+
}
|
|
436
|
+
})
|
|
437
|
+
})
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// 定位流程: 缓存 > 判断环境(APP,小程序,企微)基于环境获取定位 > 地图商高精度定位 > 地图商城市ip定位
|
|
441
|
+
const getLocationPromise = async (): Promise<Location> => {
|
|
442
|
+
let location: Location = null
|
|
443
|
+
|
|
444
|
+
// 在 SPU 容器里使用 Native-API 的定位
|
|
445
|
+
if (window?.Native?.getLocation) {
|
|
446
|
+
location = await getLocationByNative()
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
if (!location) {
|
|
450
|
+
location = await getLocationByNavigator()
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
if (!location) {
|
|
454
|
+
if (mapService.type === 'amap') {
|
|
455
|
+
location = await getLocationByAmap()
|
|
456
|
+
// ip城市定位结果不精确 但总比定不到位好
|
|
457
|
+
if (!location) {
|
|
458
|
+
location = await getCityLocationByAmap()
|
|
459
|
+
}
|
|
460
|
+
} else if (mapService.type === 'tencent') {
|
|
461
|
+
location = await getIPLocationByTMap()
|
|
462
|
+
} else if (mapService.type === 'baidu') {
|
|
463
|
+
location = await getLocationByBMap()
|
|
464
|
+
// ip城市定位结果不精确 但总比定不到位好
|
|
465
|
+
if (!location) {
|
|
466
|
+
location = await getCityLocationByBMap()
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if (!location) {
|
|
472
|
+
location = await getIPLocationByIpaas()
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// 开发模式下为了方便测试提供虚拟定位
|
|
476
|
+
if (!location && urlquery.isvirtuallocation) {
|
|
477
|
+
location = {
|
|
478
|
+
longitude: '116.397454',
|
|
479
|
+
latitude: '39.908671'
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
if (location && !location.address) {
|
|
484
|
+
location.address = (await getAddress(location)) || '经纬度获取成功,但地址获取失败。'
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
return location
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
// WGS84 GCJ-02 BD-09 坐标系
|
|
491
|
+
// https://www.jianshu.com/p/559029832a67
|
|
492
|
+
async function getLocation() {
|
|
493
|
+
await mapService.init()
|
|
494
|
+
// debugger
|
|
495
|
+
// 缓存30秒
|
|
496
|
+
if (datetime && Date.now() - datetime <= cachetime && lastLocation && !runing) {
|
|
497
|
+
return cloneDeep(lastLocation)
|
|
498
|
+
}
|
|
499
|
+
// 兼容同时间发起多个
|
|
500
|
+
if (runing && locationPromise) {
|
|
501
|
+
return locationPromise
|
|
502
|
+
}
|
|
503
|
+
// console.log('runing')
|
|
504
|
+
runing = true
|
|
505
|
+
locationPromise = getLocationPromise()
|
|
506
|
+
const locationRes = await locationPromise
|
|
507
|
+
runing = false
|
|
508
|
+
if (locationRes) {
|
|
509
|
+
datetime = Date.now()
|
|
510
|
+
lastLocation = locationRes
|
|
511
|
+
}
|
|
512
|
+
return locationRes
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
// 逆地址解析
|
|
516
|
+
const getAddress = async (position: Location): Promise<string> => {
|
|
517
|
+
await mapService.init()
|
|
518
|
+
|
|
519
|
+
let address = ''
|
|
520
|
+
|
|
521
|
+
// 先统一用ipaas解析 因为需要储存一致的地址格式(各地图商逆地址查询的地址格式不统一)
|
|
522
|
+
// 如果不行再按照各地图商解析
|
|
523
|
+
address = await getAddressByIpaas(position)
|
|
524
|
+
|
|
525
|
+
if (!address) {
|
|
526
|
+
if (mapService.type === 'amap') {
|
|
527
|
+
address = await getAddressByAmap(position)
|
|
528
|
+
} else if (mapService.type === 'tencent') {
|
|
529
|
+
address = await getAddressByTMap(position)
|
|
530
|
+
} else if (mapService.type === 'baidu') {
|
|
531
|
+
address = await getAddressByBmap(position)
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
return address
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// const getDistance = async (p1: [number, number], p2: [number, number]) => {
|
|
538
|
+
// await mapService.init()
|
|
539
|
+
// return window.AMap.GeometryUtil.distance(p1, p2)
|
|
540
|
+
// }
|
|
541
|
+
|
|
542
|
+
// 两个经纬度距离计算
|
|
543
|
+
const getDistance = async (latlng1: [number, number], latlng2: [number, number]) => {
|
|
544
|
+
// console.log(latlng1)
|
|
545
|
+
// console.log(latlng2)
|
|
546
|
+
const lng1 = Number(latlng1[0])
|
|
547
|
+
const lat1 = Number(latlng1[1])
|
|
548
|
+
const lng2 = Number(latlng2[0])
|
|
549
|
+
const lat2 = Number(latlng2[1])
|
|
550
|
+
const radLat1 = (lat1 * Math.PI) / 180.0
|
|
551
|
+
const radLat2 = (lat2 * Math.PI) / 180.0
|
|
552
|
+
const a = radLat1 - radLat2
|
|
553
|
+
const b = (lng1 * Math.PI) / 180.0 - (lng2 * Math.PI) / 180.0
|
|
554
|
+
let s =
|
|
555
|
+
2 *
|
|
556
|
+
Math.asin(
|
|
557
|
+
Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2))
|
|
558
|
+
)
|
|
559
|
+
s = s * 6378.137 // EARTH_RADIUS
|
|
560
|
+
s = Math.round(s * 10000) / 10000
|
|
561
|
+
return s * 1000
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
export { getLocation, getAddress, getDistance }
|
package/src/map/utils.ts
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
function transformLat (x: number, y: number) {
|
|
2
|
+
let ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x))
|
|
3
|
+
ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0
|
|
4
|
+
ret += (20.0 * Math.sin(y * Math.PI) + 40.0 * Math.sin(y / 3.0 * Math.PI)) * 2.0 / 3.0
|
|
5
|
+
ret += (160.0 * Math.sin(y / 12.0 * Math.PI) + 320 * Math.sin(y * Math.PI / 30.0)) * 2.0 / 3.0
|
|
6
|
+
return ret
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function transformLon (x: number, y: number) {
|
|
10
|
+
let ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x))
|
|
11
|
+
ret += (20.0 * Math.sin(6.0 * x * Math.PI) + 20.0 * Math.sin(2.0 * x * Math.PI)) * 2.0 / 3.0
|
|
12
|
+
ret += (20.0 * Math.sin(x * Math.PI) + 40.0 * Math.sin(x / 3.0 * Math.PI)) * 2.0 / 3.0
|
|
13
|
+
ret += (150.0 * Math.sin(x / 12.0 * Math.PI) + 300.0 * Math.sin(x / 30.0 * Math.PI)) * 2.0 / 3.0
|
|
14
|
+
return ret
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function outOfChina (lng: number, lat: number) {
|
|
18
|
+
return (lng < 72.004 || lng > 137.8347) || (lat < 0.8293 || lat > 55.8271)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function delta (lng: number, lat: number) {
|
|
22
|
+
const a = 6378245.0 // 地球长半轴
|
|
23
|
+
const ee = 0.00669342162296594323 // 扁率
|
|
24
|
+
let dLat = transformLat(lng - 105.0, lat - 35.0)
|
|
25
|
+
let dLng = transformLon(lng - 105.0, lat - 35.0)
|
|
26
|
+
const radLat = lat / 180.0 * Math.PI
|
|
27
|
+
let magic = Math.sin(radLat)
|
|
28
|
+
magic = 1 - ee * magic * magic
|
|
29
|
+
const sqrtMagic = Math.sqrt(magic)
|
|
30
|
+
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * Math.PI)
|
|
31
|
+
dLng = (dLng * 180.0) / (a / sqrtMagic * Math.cos(radLat) * Math.PI)
|
|
32
|
+
return {
|
|
33
|
+
lat: dLat,
|
|
34
|
+
lng: dLng
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function wgs84ToGcj02 (lng: number, lat: number) {
|
|
39
|
+
if (outOfChina(lng, lat)) {
|
|
40
|
+
return {
|
|
41
|
+
lng: lng,
|
|
42
|
+
lat: lat
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const d = delta(lng, lat)
|
|
46
|
+
return {
|
|
47
|
+
lng: lng + d.lng,
|
|
48
|
+
lat: lat + d.lat
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* 坐标常量说明:
|
|
56
|
+
* COORDINATES_WGS84 = 1, WGS84坐标
|
|
57
|
+
* COORDINATES_WGS84_MC = 2, WGS84的平面墨卡托坐标
|
|
58
|
+
* COORDINATES_GCJ02 = 3,GCJ02坐标
|
|
59
|
+
* COORDINATES_GCJ02_MC = 4, GCJ02的平面墨卡托坐标
|
|
60
|
+
* COORDINATES_BD09 = 5, 百度bd09经纬度坐标
|
|
61
|
+
* COORDINATES_BD09_MC = 6,百度bd09墨卡托坐标
|
|
62
|
+
* COORDINATES_MAPBAR = 7,mapbar地图坐标
|
|
63
|
+
* COORDINATES_51 = 8,51地图坐标
|
|
64
|
+
*/
|
|
65
|
+
const BMapTransformBD09ToGCJ02Points = (points: any[]) => {
|
|
66
|
+
return new Promise((resolve, reject) => {
|
|
67
|
+
new window.BMap.Convertor().translate(points, 5, 3, (data: any) => {
|
|
68
|
+
if (!data.status) {
|
|
69
|
+
resolve(data.points)
|
|
70
|
+
} else {
|
|
71
|
+
console.error(data)
|
|
72
|
+
// reject(data.status)
|
|
73
|
+
resolve(points)
|
|
74
|
+
}
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const BMapTransformGCJ02ToBD09Points = (points: any[]) => {
|
|
80
|
+
return new Promise((resolve, reject) => {
|
|
81
|
+
const convertor = new window.BMap.Convertor()
|
|
82
|
+
convertor.translate(points, 3, 5, (data: any) => {
|
|
83
|
+
if (!data.status) {
|
|
84
|
+
resolve(data.points)
|
|
85
|
+
} else {
|
|
86
|
+
console.error(data)
|
|
87
|
+
// reject(data.status)
|
|
88
|
+
resolve(points)
|
|
89
|
+
}
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export {
|
|
95
|
+
wgs84ToGcj02,
|
|
96
|
+
BMapTransformBD09ToGCJ02Points,
|
|
97
|
+
BMapTransformGCJ02ToBD09Points
|
|
98
|
+
}
|