Yansen 2 years ago
parent
commit
5a5200735e

BIN
public/images/close.png View File


BIN
public/images/pg4/btn_badge.png View File


BIN
public/images/pg4/btn_share.png View File


BIN
public/images/pg4/planting.png View File


BIN
public/images/share.jpg View File


BIN
public/images/电视台二维码.png View File


BIN
public/video/和平宣言-视频-压缩.mp4 View File


+ 14
- 6
src/components/Btn.vue View File

@@ -3,21 +3,29 @@
3 3
 </template>
4 4
 
5 5
 <script setup>
6
+  const props = defineProps({
7
+    frontColor: {
8
+      type: String,
9
+      default: '#EEDDC1'
10
+    },
11
+    backColor: {
12
+      type: String,
13
+      default: '#9C8B7C'
14
+    },
15
+  });
6 16
 </script>
7 17
 
8 18
 <style lang="less" scoped>
9 19
 
10 20
 .btn {
11
-  @color: #9C8B7C;
12
-
13 21
   position: relative;
14 22
   min-width: 30vw;
15 23
   height: 10vw;
16 24
   line-height: 10vw;
17 25
   display: inline-block;
18 26
   margin: auto;
19
-  color: #EEDDC1;
20
-  background: @color;
27
+  color: v-bind(frontColor);
28
+  background: v-bind(backColor);
21 29
   text-align: center;
22 30
   box-sizing: border-box;
23 31
   padding: 0 1em;
@@ -26,8 +34,8 @@
26 34
     content: '';
27 35
     width: 100%;
28 36
     height: 100%;
29
-    border-bottom: 2px solid @color;
30
-    border-right: 2px solid @color;
37
+    border-bottom: 2px solid v-bind(backColor);
38
+    border-right: 2px solid v-bind(backColor);
31 39
     position: absolute;
32 40
     bottom: -4px;
33 41
     right: -4px;

+ 80
- 0
src/components/Modal.vue View File

@@ -0,0 +1,80 @@
1
+<template>
2
+  <div class="modal-wrapper animate__animated animate__fadeIn" @touchmove.prevent @click.passive="onClickMask">
3
+    <div class="modal-body" :class="bodyClass" :style="bodyStyle" @click.stop>
4
+      <div v-if="close" class="modal-close" @click.stop="onClickClose"></div>
5
+      <slot />
6
+    </div>
7
+  </div>
8
+</template>
9
+
10
+<script setup>
11
+  const props = defineProps({
12
+    bodyClass: undefined,
13
+    bodyStyle: undefined,
14
+    maskClick: {
15
+      type: Boolean,
16
+      default: true
17
+    },
18
+    close: {
19
+      type: Boolean,
20
+      default: true
21
+    }
22
+  });
23
+
24
+  const emit = defineEmits(['cancel'])
25
+
26
+  const onClickMask = () => {
27
+    if (props.maskClick) {
28
+      emit('cancel');
29
+    }
30
+  }
31
+
32
+  const onClickClose = () => {
33
+    emit('cancel');
34
+  }
35
+</script>
36
+
37
+<style lang="less" scoped>
38
+.modal-wrapper {
39
+  position: fixed;
40
+  top: 0;
41
+  left: 0;
42
+  width: 100vw;
43
+  height: 100vh;
44
+  z-index: 1000;
45
+  animation-duration: 200ms;
46
+  background: transparent;
47
+    background: rgba(0, 0, 0, 0.5);
48
+
49
+    display: flex;
50
+    align-items: center;
51
+    justify-content: center;
52
+  
53
+  .modal-mask {
54
+    position: absolute;
55
+    z-index: 1;
56
+    width: 100%;
57
+    height: 100%;
58
+    left: 0;
59
+    top: 0;
60
+    background: rgba(0, 0, 0, 0.5);
61
+  }
62
+
63
+  .modal-body {
64
+    flex: none;
65
+    position: relative;
66
+    box-sizing: border-box;
67
+
68
+    .modal-close {
69
+      position: absolute;
70
+      width: 40px;
71
+      height: 40px;
72
+      background-image: url(/images/close.png);
73
+      background-size: 100% 100%;
74
+      background-repeat: no-repeat;
75
+      right: -16px;
76
+      top: -16px;
77
+    }
78
+  }
79
+}
80
+</style>

+ 54
- 0
src/components/PageLoading.vue View File

@@ -0,0 +1,54 @@
1
+<template>
2
+  <Modal :close="false" v-if="loading">
3
+    <div class="pg-loading">
4
+      <div class="loading-icon">
5
+        <img src="/images/logo.png" alt="">
6
+      </div>
7
+      <div class="loading-content txt">
8
+        {{text}}
9
+      </div>
10
+    </div>
11
+  </Modal>
12
+</template>
13
+
14
+<script setup>
15
+  import Modal from './Modal.vue';
16
+
17
+  const props = defineProps({
18
+    text: {
19
+      type: String,
20
+      default: '请稍候...'
21
+    },
22
+    loading: Boolean
23
+  })
24
+</script>
25
+
26
+<style lang="less" scoped>
27
+.pg-loading {
28
+  width: 100%;
29
+
30
+  .loading-icon {
31
+    width: 24px;
32
+    height: 24px;
33
+    margin: auto;
34
+    animation: loading-circle 2s linear infinite;
35
+  }
36
+
37
+  @keyframes loading-circle {
38
+    from {
39
+      transform: rotate(0);
40
+    }
41
+
42
+    to {
43
+      transform: rotate(360deg);
44
+    }
45
+  }
46
+
47
+  .loading-content {
48
+    text-align: center;
49
+    color: #fff;
50
+    margin-top: 24px;
51
+    letter-spacing: 2px;
52
+  }
53
+}
54
+</style>

+ 57
- 0
src/pages/pg4/Badge.vue View File

@@ -0,0 +1,57 @@
1
+<template>
2
+  <Modal v-if="show" @cancel="emit('cancel')">
3
+    <div class="badge-wrapper pg-bg txt">
4
+      <div class="title">领取徽章</div>
5
+      <div class="qrcode">
6
+        <img src="/images/电视台二维码.png" alt="">
7
+        <div>长按识别二维码</div>
8
+      </div>
9
+      <div class="desc">
10
+        关注“南京广播电视台”回复<br>
11
+        “<span class="keyword">紫金草</span>”<br>
12
+        领取纪紫金草徽章<br>
13
+        (数量有限,领完即止)
14
+      </div>
15
+    </div>
16
+  </Modal>
17
+</template>
18
+
19
+<script setup>
20
+  import { ref } from 'vue';
21
+  import Modal from '@/components/Modal.vue';
22
+
23
+  const props = defineProps({
24
+    country: String,
25
+    show: Boolean
26
+  })
27
+
28
+  const emit = defineEmits(['cancel']);
29
+</script>
30
+
31
+<style lang="less" scoped>
32
+.badge-wrapper {
33
+  width: 70vw;
34
+  border-radius: 16px;
35
+  overflow: hidden;
36
+  text-align: center;
37
+  padding: 1em;
38
+  box-sizing: border-box;
39
+
40
+  .title {
41
+    font-size: 18px;
42
+    margin-bottom: 10px;
43
+  }
44
+
45
+  .qrcode {
46
+    width: 160px;
47
+    margin: auto;
48
+    font-size: 14px;
49
+  }
50
+
51
+  .keyword {
52
+    font-size: 18px;
53
+    font-weight: 700;
54
+    color: #A75BAD;
55
+  }
56
+}
57
+</style>

+ 44
- 0
src/pages/pg4/Flower.vue View File

@@ -0,0 +1,44 @@
1
+<template>
2
+  <Modal v-if="show" @cancel="emit('cancel')">
3
+    <div class="txt modal-flower">
4
+      <p class="title">{{country}}种植数量: 12896690</p>
5
+      <p class="planting" @click="onPlanting">
6
+        <img src="/images/pg4/planting.png" alt="">
7
+      </p>
8
+    </div>
9
+  </Modal>
10
+</template>
11
+
12
+<script setup>
13
+  import Modal from '@/components/Modal.vue';
14
+
15
+  const props = defineProps({
16
+    country: String,
17
+    show: Boolean
18
+  })
19
+
20
+  const emit = defineEmits(['cancel', 'planted']);
21
+
22
+  const onPlanting = () => {
23
+    //
24
+    emit('planted');
25
+  }
26
+
27
+</script>
28
+
29
+<style lang="less" scoped>
30
+.modal-flower {
31
+  width: 70vw;
32
+  text-align: center;
33
+
34
+  .title {
35
+    color: #fff;
36
+    font-size: 16px;
37
+  }
38
+
39
+  .planting {
40
+    width: 30vw;
41
+    margin: auto;
42
+  }
43
+}
44
+</style>

+ 132
- 0
src/pages/pg4/Map.vue View File

@@ -0,0 +1,132 @@
1
+<template>
2
+  <div class="map-pg" ref="el"></div>
3
+  <PageLoading :loading="loading" />
4
+</template>
5
+
6
+<script setup>
7
+  import { onMounted, ref, watch } from 'vue';
8
+  import PageLoading from '@/components/PageLoading.vue';
9
+  import countryGPS from '@/utils/country_gps';
10
+  import { getCountry } from '@/utils/maputil';
11
+  // import AMapLoader from '@amap/amap-jsapi-loader';
12
+  // import { getGPSOfBDCountries } from './gps';
13
+
14
+  const emit = defineEmits(['click']);
15
+
16
+  const el = ref();
17
+  const mapRef = ref();
18
+  const loading = ref(false);
19
+
20
+  // 展示部分国家
21
+  const mockCountries = [
22
+    '中国',
23
+    '俄罗斯',
24
+    '哈萨克斯坦',
25
+    '伊朗',
26
+    '印度',
27
+    '泰国',
28
+  ];
29
+
30
+  // getGPSOfBDCountries();
31
+
32
+  onMounted(() => {
33
+    const map = new BMap.Map(el.value);
34
+    const point = new BMap.Point(116.404, 39.915); // 天安门
35
+    map.centerAndZoom(point, 3);
36
+    mapRef.value = map;
37
+
38
+    // 绑定事件
39
+    map.addEventListener('click', (e) => {
40
+      console.log('-----start-----')
41
+      loading.value = true;
42
+      const { point } = e;
43
+      getCountry(point.lng, point.lat).then(x => {
44
+        emit('click', x);
45
+        loading.value = false;
46
+      console.log('-----end-----')
47
+      }).catch((err) => {
48
+        console.error(err);
49
+        loading.value = false;
50
+      });
51
+    });
52
+
53
+    // 显示 marker
54
+    const icon = new BMap.Icon('./images/logo.png', new BMap.Size(16, 16));    
55
+    mockCountries.forEach(country => {
56
+        const target = countryGPS[country];
57
+        if (!target) {
58
+          console.error(`${country} 在世界GPS列表中不存在`)
59
+          return;
60
+        }
61
+        
62
+        const point = new BMap.Point(target[0], target[1]);
63
+        const marker = new BMap.Marker(point, { icon });
64
+        map.addOverlay(marker);
65
+      });
66
+
67
+    // window._AMapSecurityConfig = {
68
+    //   securityJsCode:'f33684b9573195f9f91a4c8bc779d7e2',
69
+    // }
70
+    // AMapLoader.load({
71
+    //   key: "378f2af0c01b00ec919ace1699f2466f",              // 申请好的Web端开发者Key,首次调用 load 时必填
72
+    //   version: "2.0",   // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
73
+    //   plugins: [],           // 需要使用的的插件列表,如比例尺'AMap.Scale'等
74
+    // }).then((AMap)=>{
75
+    //   const map = new AMap.Map(el.value, {
76
+    //     mapStyle: 'amap://styles/bff59c60c62af794ee93f1befde78625',
77
+    //     zoom: 3,
78
+    //   });
79
+
80
+    //   const countries = Object.keys(countryGPS);
81
+    //   countries.forEach((country) => {
82
+    //     const position = countryGPS[country];
83
+    //     const found = mockCountries.filter(x => x===country)[0];
84
+
85
+    //     console.log('----position---->', position);
86
+        
87
+    //     const marker = new AMap.Marker({
88
+    //       map,
89
+    //       offset:[-100, -16],
90
+    //       content: `
91
+    //         <div class="map-marker-box">
92
+    //           <div class="map-marker-title">${country}</div>
93
+    //           ${found ? '<div class="map-marker-icon"/>' : ''}
94
+    //         </div>
95
+    //       `,
96
+    //       position,
97
+    //     });
98
+      // });
99
+
100
+      // mockCountries.forEach(country => {
101
+      //   const target = countryGPS[country];
102
+      //   if (!target) {
103
+      //     console.error(`${country} 在世界GPS列表中不存在`)
104
+      //     return;
105
+      //   }
106
+        
107
+      //   const marker = new AMap.Marker({
108
+      //     map,
109
+      //     offset:[-100, -16],
110
+      //     content: `
111
+      //       <div class="map-marker-box">
112
+      //         <div class="map-marker-title">${country}</div>
113
+      //         <div class="map-marker-icon"/>
114
+      //       </div>
115
+      //     `,
116
+      //     position: target,
117
+      //   });
118
+      // });
119
+
120
+    // }).catch(e => {
121
+    //   console.error(e);
122
+    // })
123
+  });
124
+
125
+</script>
126
+
127
+<style lang="less" scoped>
128
+.map-pg {
129
+  width: 100%;
130
+  height: 100%;
131
+}
132
+</style>

+ 43
- 0
src/pages/pg4/Rule.vue View File

@@ -0,0 +1,43 @@
1
+<template>
2
+  <Modal v-if="show" @cancel="onCancel">
3
+    <div class="pg-bg txt modal-rule">
4
+      <h3>参与规则</h3>
5
+      <ul>
6
+        <li>选择要播撒的种子,并进行播种。</li>
7
+        <li>种植完成后可领取实体资金草徽章一枚。</li>
8
+      </ul>
9
+    </div>
10
+  </Modal>
11
+</template>
12
+
13
+<script setup>
14
+  import { ref } from 'vue';
15
+  import Modal from '@/components/Modal.vue';
16
+
17
+  const show = ref(true);
18
+
19
+  const onCancel = () => {
20
+    show.value = false;
21
+  }
22
+</script>
23
+
24
+<style lang="less" scoped>
25
+.modal-rule {
26
+  box-sizing: border-box;
27
+  padding: 0 1em;
28
+  width: 80vw;
29
+  text-align: center;
30
+  border-radius: 16px;
31
+  overflow: hidden;
32
+
33
+  h3 {
34
+    font-size: 18px;
35
+    font-size: 700;
36
+  }
37
+
38
+  ul {
39
+    text-align: left;
40
+    margin-top: 0;
41
+  }
42
+}
43
+</style>

+ 41
- 0
src/pages/pg4/Share.vue View File

@@ -0,0 +1,41 @@
1
+<template>
2
+  <div class="share-wrapper">
3
+    <div class="share-action">
4
+      <img src="/images/pg4/btn_share.png" alt="" @click="emit('share')">
5
+      <img src="/images/pg4/btn_badge.png" alt="" @click="emit('badge')">
6
+    </div>
7
+    <div class="share-txt txt">
8
+      目前总种植数量: 35896690
9
+    </div>
10
+  </div>
11
+</template>
12
+
13
+<script setup>
14
+  const emit = defineEmits(['share', 'badge'])
15
+</script>
16
+
17
+<style lang="less" scoped>
18
+.share-wrapper {
19
+  background-image: linear-gradient(transparent, #EDEEF0 40%, #EDEEF0);
20
+  box-sizing: border-box;
21
+  padding: 10px 1em;
22
+  width: 100%;
23
+
24
+  .share-action {
25
+    display: flex;
26
+    align-items: center;
27
+    justify-content: space-around;
28
+
29
+    img {
30
+      flex: none;
31
+      width: 35vw;
32
+    }
33
+  }
34
+
35
+  .share-txt {
36
+    margin-top: 6px;
37
+    text-align: center;
38
+    letter-spacing: 2px;
39
+  }
40
+}
41
+</style>

+ 67
- 0
src/pages/pg4/gps.js View File

@@ -0,0 +1,67 @@
1
+import countryGPS from '@/utils/country_gps';
2
+import { transform } from '@/utils/coordinate';
3
+
4
+export function getGPSOfBDCountries() {
5
+  return new Promise((resolve) => {    
6
+    const allGPS = {};
7
+    const countries = Object.keys(countryGPS);
8
+    let transNum = 0;
9
+    const convertor = new BMap.Convertor();
10
+
11
+    let times = 0;
12
+    const inst = setInterval(() => {
13
+      const country = countries[times];
14
+
15
+      const gps = countryGPS[country];
16
+
17
+      console.log('gps', gps);
18
+
19
+      const gpsPoint = new BMap.Point(gps[0], gps[1]);
20
+      // 这个地方的参数估计有问题
21
+      convertor.translate([gpsPoint], 1, 5, ({status, points}) => {
22
+        transNum += 1;
23
+        if (status === 0) {
24
+          const [bdPoint] = points;
25
+
26
+          allGPS[country] = {
27
+            gps: gpsPoint,
28
+            bd: bdPoint,
29
+          }
30
+        }
31
+
32
+        console.log(country, points, transNum);
33
+
34
+        if (transNum >= countries.length) {
35
+          console.log(JSON.stringify(allGPS))
36
+          resolve(allGPS);
37
+        }
38
+      });
39
+
40
+      
41
+      times ++;
42
+      if (times >= countries.length) {
43
+        clearInterval(inst);
44
+      }
45
+    }, 1000);
46
+
47
+  });
48
+}
49
+
50
+export function getGPSOfGD() {
51
+  const countries = Object.keys(countryGPS);
52
+
53
+  const allGPS = countries.reduce((acc, country) => {
54
+    const gps = countryGPS[country];
55
+    const gd = transform(gps.join(','));
56
+
57
+    return {
58
+      ...acc,
59
+      [country]: {
60
+        gps,
61
+        gd
62
+      }
63
+    }
64
+  }, {});
65
+
66
+  console.log(JSON.stringify(allGPS));
67
+}

+ 51
- 25
src/pages/pg4/index.vue View File

@@ -1,31 +1,57 @@
1 1
 <template>
2
-  <div class="page" ref="el"></div>
2
+  <div class="page pg-bg pg4">
3
+    <Map @click="onMapClick" />
4
+    <Rule />
5
+    <Flower
6
+      :show="flowerShow"
7
+      :country="countryRef"
8
+      @planted="onPlanted"
9
+      @cancel="flowerShow = false"
10
+    />
11
+    <Share
12
+      v-if="planted"
13
+      class="share abs"
14
+      @share="onShare"
15
+      @badge="badgeShow = true"
16
+    />
17
+    <Badge :show="badgeShow" @cancel="badgeShow = false" />
18
+  </div>
3 19
 </template>
4 20
 
5 21
 <script setup>
6
-  import { onMounted, ref } from 'vue';
7
-  // import AMapLoader from '@amap/amap-jsapi-loader';
22
+  import { onMounted, ref, watch } from 'vue';
23
+  import { useRouter } from 'vue-router';
24
+  import Rule from './Rule.vue';
25
+  import Map from './Map.vue';
26
+  import Flower from './Flower.vue';
27
+  import Share from './Share.vue';
28
+  import Badge from './Badge.vue';
8 29
 
9
-  const el = ref();
30
+  const router = useRouter();
31
+  const countryRef = ref();
32
+  const flowerShow = ref();
33
+  const planted = ref(false);
34
+  const badgeShow = ref(false);
10 35
 
11
-  onMounted(() => {
12
-    const map = new BMap.Map(el.value);
13
-    const point = new BMap.Point(116.404, 39.915); // 天安门
14
-    map.centerAndZoom(point, 3);
15
-    // window._AMapSecurityConfig = {
16
-    //   securityJsCode:'f33684b9573195f9f91a4c8bc779d7e2',
17
-    // }
18
-    // AMapLoader.load({
19
-    //   key: "378f2af0c01b00ec919ace1699f2466f",              // 申请好的Web端开发者Key,首次调用 load 时必填
20
-    //   version: "2.0",   // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
21
-    //   plugins: [],           // 需要使用的的插件列表,如比例尺'AMap.Scale'等
22
-    // }).then((AMap)=>{
23
-    //   const map = new AMap.Map(el.value, {
24
-    //     mapStyle: 'amap://styles/bff59c60c62af794ee93f1befde78625',
25
-    //     zoom: 3,
26
-    //   });
27
-    // }).catch(e => {
28
-    //   console.error(e);
29
-    // })
30
-  });
31
-</script>
36
+  const onMapClick = (country) => {
37
+    countryRef.value = country;
38
+    flowerShow.value = true;
39
+  }
40
+
41
+  const onPlanted = () => {
42
+    planted.value = true;
43
+    flowerShow.value = false;
44
+  }
45
+
46
+  const onShare = () => {
47
+    router.push('/share')
48
+  }
49
+
50
+</script>
51
+
52
+<style lang="less">
53
+.share {
54
+  bottom: 0;
55
+  left: 0;
56
+}
57
+</style>

+ 67
- 0
src/pages/pg4/video.vue View File

@@ -0,0 +1,67 @@
1
+<template>
2
+  <div class="page pg-bg video-pg">
3
+    <video
4
+      src="/video/和平宣言-视频-压缩.mp4"
5
+      preload="preload"
6
+      controls="controls"
7
+      ref="mediaRef"
8
+      @ended="show = true"
9
+    ></video>
10
+    <div class="play-action animate__animated animate__fadeIn" v-if="show">
11
+      <div class="btns">
12
+        <Btn front-color="#000" back-color="rgba(255,255,255, 1)" @click="onReplay">重播</Btn>
13
+        <Btn front-color="#000" back-color="rgba(255,255,255, 1)" style="margin-left: 24px" @click="onNext">下一步</Btn>
14
+      </div>
15
+    </div>
16
+  </div>
17
+</template>
18
+
19
+<script setup>
20
+  import { ref } from 'vue';
21
+  import { useRouter } from 'vue-router';
22
+  import Btn from '@/components/Btn.vue';
23
+  
24
+  const router = useRouter();
25
+  const mediaRef = ref();
26
+  const show = ref(false);
27
+
28
+  const onReplay = () => {
29
+    mediaRef.value.play();
30
+    show.value = false;
31
+  }
32
+
33
+  const onNext = () => {
34
+    router.push('/pg4/next')
35
+  }
36
+</script>
37
+
38
+<style lang="less" scoped>
39
+.video-pg {
40
+  position: relative;
41
+
42
+  video {
43
+    position: relative;
44
+    width: 100%;
45
+    height: 100%;
46
+    z-index: 1;
47
+  }
48
+
49
+  .play-action {
50
+    position: absolute;
51
+    z-index: 2;
52
+    top: 0;
53
+
54
+    width: 100%;
55
+    height: 100%;
56
+    background: rgba(0, 0, 0, 0.5);
57
+
58
+    display: flex;
59
+    align-items: center;
60
+    justify-content: center;
61
+
62
+    .btns {
63
+
64
+    }
65
+  }
66
+}
67
+</style>

+ 17
- 0
src/pages/share/index.vue View File

@@ -0,0 +1,17 @@
1
+<template>
2
+  <div class="share-pg">
3
+    <img src="/images/share.jpg" alt="">
4
+  </div>
5
+</template>
6
+
7
+<script setup>
8
+
9
+</script>
10
+
11
+<style lang="less" scoped>
12
+.share-pg {
13
+  position: relative;
14
+  width: 100vw;
15
+  height: 100vh;
16
+}
17
+</style>

+ 3
- 1
src/router.js View File

@@ -6,7 +6,9 @@ const routes = [
6 6
   { path: '/', component: () => import('@/pages/index.vue') },
7 7
   { path: '/bk1', component: () => import('@/pages/bk1/index.vue') },
8 8
   { path: '/pg2-2', component: () => import('@/pages/pg2-2/index.vue') },
9
-  { path: '/pg4', component: () => import('@/pages/pg4/index.vue') },
9
+  { path: '/pg4', component: () => import('@/pages/pg4/video.vue') },
10
+  { path: '/pg4/next', component: () => import('@/pages/pg4/index.vue') },
11
+  { path: '/share', component: () => import('@/pages/share/index.vue') },
10 12
 ]
11 13
 
12 14
 const router = createRouter({

+ 54
- 0
src/utils/coordinate.js View File

@@ -0,0 +1,54 @@
1
+
2
+/**  
3
+ * 单点坐标纠偏
4
+ */
5
+const pi = 3.14159265358979324;
6
+const a = 6378245.0;
7
+const ee = 0.00669342162296594323;
8
+const x_pi = 3.14159265358979324 * 3000.0 / 180.0;
9
+
10
+function outOfChina(lat, lon) {
11
+  if(lon < 72.004 || lon > 137.8347)
12
+      return true;
13
+  if(lat < 0.8293 || lat > 55.8271)
14
+      return true;
15
+  return false;
16
+};
17
+
18
+function transformLat(x, y) {
19
+  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));
20
+  ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
21
+  ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
22
+  ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
23
+  return ret;
24
+};
25
+
26
+function transformLon(x, y) {
27
+  let ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
28
+  ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
29
+  ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
30
+  ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0 * pi)) * 2.0 / 3.0;
31
+  return ret;
32
+};
33
+
34
+// wgs84 转 gcj02
35
+export function transform (location) {
36
+  const [wgLon, wgLat] = location.split(',').map(x => x - 0);
37
+  const latlng = [];
38
+  if(outOfChina(wgLat, wgLon)) {
39
+    latlng[0] = wgLon;
40
+    latlng[1] = wgLat;
41
+    return latlng;
42
+  }
43
+  let dLat = transformLat(wgLon - 105.0, wgLat - 35.0);
44
+  let dLon = transformLon(wgLon - 105.0, wgLat - 35.0);
45
+  const radLat = wgLat / 180.0 * pi;
46
+  let magic = Math.sin(radLat);
47
+  magic = 1 - ee * magic * magic;
48
+  const sqrtMagic = Math.sqrt(magic);
49
+  dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
50
+  dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
51
+  latlng[0] = wgLon + dLon;
52
+  latlng[1] = wgLat + dLat;
53
+  return latlng;
54
+};

+ 202
- 0
src/utils/country_gps.js View File

@@ -0,0 +1,202 @@
1
+
2
+export default {
3
+  "阿富汗": [63.845419, 32.932881],
4
+  "阿尔巴尼亚": [20.04553, 40.236795],
5
+  "阿尔及利亚": [2.329836, 26.237482],
6
+  "美属萨摩亚": [-170.829361, -14.572052],
7
+  "安道尔": [1.35795, 42.112186],
8
+  "安哥拉": [16.546512, -13.780866],
9
+  "安提瓜和巴布达": [-61.807301, 17.056604],
10
+  "阿根廷": [-68.170846, -40.593588],
11
+  "亚美尼亚": [44.738974, 40.023823],
12
+  "阿鲁巴": [-69.898198, 12.449642],
13
+  "澳大利亚": [133.719944, -26.475613],
14
+  "奥地利": [14.310332, 47.145488],
15
+  "阿塞拜疆": [47.53841, 40.371428],
16
+  "巴哈马": [-77.394555, 25.009396],
17
+
18
+  "孟加拉国": [89.93617, 23.754802],
19
+  "巴巴多斯": [-59.5317, 13.093871],
20
+  "白俄罗斯": [27.434815, 53.225932],
21
+  "比利时": [4.335889, 50.586323],
22
+  "伯利兹": [-89.049292, 16.249301],
23
+  "贝宁": [2.094167, 8.837661],
24
+  "不丹": [90.296541, 27.208804],
25
+  "玻利维亚": [-64.561985, -17.4458],
26
+  "波斯尼亚和黑塞哥维那": [18.26, 43.52],
27
+  "博茨瓦纳": [21.458304, -24.725057],
28
+  "巴西": [-54.154034, -9.152088],
29
+  "英属维尔京群岛": [-64.714132, 18.322705],
30
+  "文莱": [114.742438,4.113674],
31
+  "保加利亚": [25.219069, 42.460541],
32
+  "布基纳法索": [-2.145688, 11.85263],
33
+  "布隆迪": [29.717485, -3.635897],
34
+  "柬埔寨": [104.448382, 12.523686],
35
+  "喀麦隆": [11.494468, 3.424938],
36
+  "加拿大": [-107.27526, 55.182101],
37
+  "佛得角": [-22.922218, 16.690972],
38
+  "开曼群岛": [-81.271273, 19.292829],
39
+  "中非共和国": [18.810124, 6.041238],
40
+  "乍得": [18.447049, 14.768537],
41
+  "智利": [-69.977876, -25.138942],
42
+  "中国": [116.416833, 39.948327],
43
+  "哥伦比亚": [-73.478806, 2.776096],
44
+  "科摩罗": [43.375844, -11.78857],
45
+  "刚果": [21.743027,-2.573788],
46
+  "哥斯达黎加": [-84.292638, 9.887252],
47
+  "科特迪瓦": [-6.155916, 6.89432],
48
+  "克罗地亚": [16.72358, 45.521662],
49
+  "古巴": [-77.986987, 21.103407],
50
+  "塞浦路斯": [32.946057, 34.936603],
51
+  "捷克共和国": [15.278066, 49.498191],
52
+  "朝鲜": [126.92294, 39.664207],
53
+  "刚果(扎伊尔)": [15.15, -4.20],
54
+  "丹麦": [8.952741, 55.948581],
55
+  "吉布提": [42.256249, 11.485377],
56
+  "多米尼加": [-70.483469, 18.649493],
57
+  "多米尼加共和国": [-70.395507, 18.603449],
58
+  "东帝汶": [125.431956, -9.124093],
59
+  "厄瓜多尔": [-78.964932, -2.21516],
60
+  "埃及": [29.594646, 25.936378],
61
+  "萨尔瓦多": [-88.584136, 13.373462],
62
+  "赤道几内亚": [10.088521, 1.30738],
63
+  "厄立特里亚": [37.648078, 15.784249],
64
+  "爱沙尼亚": [25.476342, 58.478596],
65
+  "埃塞俄比亚": [38.786169, 7.794486],
66
+
67
+  "法罗群岛": [-6.797398, 61.97106],
68
+  "斐济": [177.672622, -17.921157],
69
+  "芬兰": [25.674431, 67.904553],
70
+  "法国": [0.906587, 47.271511],
71
+  "法属圭亚那": [-53.494303, 3.511379],
72
+  "法属波利尼西亚": [-149.49538, -17.675057],
73
+  "加蓬": [11.63449, -0.962011],
74
+  "冈比亚": [-14.934767, 13.633996],
75
+  "格鲁吉亚": [43.068284, 42.032932],
76
+  "德国": [9.921454, 50.615325],
77
+  "加纳": [-1.35073, 7.57263],
78
+  "希腊": [21.740949, 38.760921],
79
+  "格陵兰": [-42.715567, 76.109625],
80
+  "瓜德罗普岛": [-61.44, 16.00],
81
+  "危地马拉": [-91.102574, 14.574812],
82
+
83
+  "几内亚": [-9.920862, 9.507233],
84
+  "几内亚比绍": [-15.258858, 11.72377],
85
+  "圭亚那": [-58.825875, 2.121864],
86
+  "海地": [-72.463939, 19.188571],
87
+
88
+  "洪都拉斯": [-85.755474, 15.090622],
89
+  "匈牙利": [19.131732, 46.477001],
90
+  "冰岛": [-18.347671, 64.920607],
91
+  "印度": [78.886416, 20.130359],
92
+  "印度尼西亚": [119.773825, -4.735047],
93
+  "伊朗": [53.25111, 31.557465],
94
+  "伊拉克": [42.709565, 32.494493],
95
+  "爱尔兰": [-8.873846, 52.611764],
96
+
97
+  "意大利": [12.380236, 42.789341],
98
+  "牙买加": [-77.705921, 17.998272],
99
+  "约旦": [35.688762, 30.054147],
100
+  "哈萨克斯坦": [65.606553, 47.208443],
101
+  "肯尼亚": [37.595164, -0.596304],
102
+  "基里巴斯": [173.394862, 0.204265],
103
+  "科威特": [47.662234, 29.06732],
104
+  "吉尔吉斯斯坦": [72.550072, 41.271747],
105
+  "老挝": [102.267255, 19.552701],
106
+  "拉脱维亚": [25.693823, 56.772585],
107
+  "黎巴嫩": [35.550681, 33.577732],
108
+  "莱索托": [27.907056, -29.883175],
109
+  "利比里亚": [-9.620946, 6.034217],
110
+  "阿拉伯利比亚民众国": [13.07, 32.49],
111
+  "列支敦士登": [9.341504, 47.06258],
112
+  "立陶宛": [23.663957, 55.006037],
113
+  "卢森堡": [6.089966, 49.584528],
114
+  "马达加斯加": [45.375062, -21.97068],
115
+  "马拉维": [34.09973, -13.53828],
116
+  "马来西亚": [101.539688, 4.765938],
117
+  "马尔代夫": [73.026071, 3.212025],
118
+  "马里": [-1.913589, 17.136474],
119
+  "马耳他": [14.439807, 35.867096],
120
+  "马提尼克岛": [-60.962083, 14.601499],
121
+  "毛里塔尼亚": [-11.585315, 20.304108],
122
+
123
+  "墨西哥": [-104.700828, 25.155423],
124
+  "密克罗尼西亚(联邦) ": [158.202146, 6.84037],
125
+  "摩尔多瓦共和国": [28.222509, 47.201738],
126
+  "莫桑比克": [34.508512, -19.208157],
127
+  "缅甸": [95.465812, 21.23136],
128
+  "纳米比亚": [15.208731, -23.22107],
129
+  "尼泊尔": [82.226627, 28.212588],
130
+  "荷兰": [5.09062, 51.889432],
131
+  "荷属安的列斯": [-69.00, 12.05],
132
+  "新喀里多尼亚": [165.306074, -21.436762],
133
+  "新西兰": [169.430911, -44.653872],
134
+  "尼加拉瓜": [-84.931331, 12.895367],
135
+  "尼日尔": [6.997375, 16.696015],
136
+  "尼日利亚": [7.508122, 9.073755],
137
+  "诺福克岛": [167.944363, -29.046645],
138
+  "北马里亚纳群岛": [145.727885, 15.188258],
139
+  "挪威": [7.427469, 60.818838],
140
+  "阿曼": [56.823005, 20.604652],
141
+  "巴基斯坦": [69.005526, 29.584602],
142
+  "帕劳": [134.543426, 7.406806],
143
+  "巴拿马": [-81.461264, 7.929068],
144
+  "巴布亚新几内亚": [143.64797, -6.699991],
145
+  "巴拉圭": [-58.790773, -23.92163],
146
+  "秘鲁": [-75.650266, -11.125338],
147
+  "菲律宾": [122.009227, 12.314208],
148
+  "波兰": [18.410598, 52.41229],
149
+  "葡萄牙": [-8.872349, 39.248058],
150
+  "波多黎各": [-66.640167, 18.24638],
151
+  "卡塔尔": [51.129232,24.730622],
152
+  "韩国": [127.536659,35.284768],
153
+  "罗马尼亚": [24.554627,44.822581],
154
+  "俄罗斯": [105.125642,60.284459],
155
+  "卢旺达": [29.708849,-2.571033],
156
+ 
157
+
158
+  "圣皮埃尔和密克隆": [-56.193589,46.421843],
159
+  
160
+  "萨摩亚": [-172.015124,-14.183153],
161
+  "圣马力诺": [12.318397,43.536617],
162
+  "圣多美和普林西比": [6.546377,-0.094488],
163
+  "沙特阿拉伯": [43.513227,21.221083],
164
+  "塞内加尔": [-14.16246,13.927042],
165
+  "塞拉利昂": [-11.777698,7.988154],
166
+  "斯洛伐克": [19.524171,48.446361],
167
+  "斯洛文尼亚": [14.859569,45.943896],
168
+  "所罗门群岛": [160.131549,-9.843937],
169
+  "索马里": [46.13307,4.728546],
170
+  "比勒陀利亚": [28.15162,-26.236597],
171
+  "西班牙": [-3.385681,38.844723],
172
+  "苏丹": [29.655658,15.472078],
173
+  "苏里南": [-56.001468,3.20082],
174
+  "斯威士兰": [31.522017,-27.033699],
175
+  "瑞典": [16.583656,63.159047],
176
+  "瑞士": [7.88977,46.727455],
177
+ 
178
+  "塔吉克斯坦": [71.165934,38.539916],
179
+  "泰国": [100.988803,16.062762],
180
+  "马其顿": [21.609549,41.361815],
181
+
182
+  "汤加": [-175.145232,-21.255308],
183
+  "突尼斯": [10.192788,36.551971],
184
+  "土耳其": [34.821265,39.413194],
185
+  "土库曼斯坦": [54.593227,39.369869],
186
+
187
+  "乌干达": [32.238125,0.172108],
188
+  "乌克兰": [31.243127,48.468653],
189
+  "阿联酋": [54.004622,23.088022],
190
+  "英国": [-2.090231,53.908945],
191
+  "坦桑尼亚": [34.736674,-7.838903],
192
+  "美国": [-101.517222,38.68111],
193
+  "美属维尔京群岛": [-64.56,18.21],
194
+  "乌拉圭": [-55.865661,-33.673849],
195
+  "乌兹别克斯坦": [64.387777,41.05238],
196
+  "瓦努阿图": [168.18,-17.45],
197
+  "委内瑞拉": [-66.252481,6.826627],
198
+  "越南": [108.281064,13.361456],
199
+  "塞尔维亚": [20.972008,43.815646],
200
+  "赞比亚": [25.431235,-14.804475],
201
+  "津巴布韦": [29.870313,-19.532838]
202
+}

+ 11
- 0
src/utils/maputil.js View File

@@ -0,0 +1,11 @@
1
+
2
+export const getCountry = (lng, lat) => {
3
+  // 天地图 https://console.tianditu.gov.cn/api/key
4
+  const tk = 'f7364a3486618e64801c69ccc54a4202';
5
+  const url = `http://api.tianditu.gov.cn/geocoder?postStr={'lon':${lng},'lat':${lat},'ver':1}&type=geocode&tk=${tk}`;
6
+  return fetch(url).then(res => res.json()).then(res => {
7
+    if (res.status == 0) {
8
+      return res.result.addressComponent.nation
9
+    }
10
+  });
11
+}