Browse Source

feat: 添加高德地图显示

TwoKe 3 năm trước cách đây
mục cha
commit
de36fcc512

+ 5 - 0
package-lock.json

@@ -4,6 +4,11 @@
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
+    "@amap/amap-jsapi-loader": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmmirror.com/@amap/amap-jsapi-loader/-/amap-jsapi-loader-1.0.1.tgz",
+      "integrity": "sha512-nPyLKt7Ow/ThHLkSvn2etQlUzqxmTVgK7bIgwdBRTg2HK5668oN7xVxkaiRe3YZEzGzfV2XgH5Jmu2T73ljejw=="
+    },
     "nanoid": {
       "version": "3.3.3",
       "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.3.tgz",

+ 1 - 0
package.json

@@ -7,6 +7,7 @@
     "build": "vue-cli-service build"
   },
   "dependencies": {
+    "@amap/amap-jsapi-loader": "^1.0.1",
     "core-js": "^3.8.3",
     "vue": "^2.6.14",
     "vue-router": "^3.5.1"

+ 51 - 0
src/assets/styles/amap.less

@@ -0,0 +1,51 @@
+// ---------------------- 高德地图显示配置
+.amap-logo { // 隐藏高德地图logo
+  display: none !important;
+}
+.amap-copyright { // 隐藏版权
+  display: none !important;
+}
+
+.fire-container { // 火焰点位
+  position: relative;
+  img {
+    display: block;
+    position: absolute;
+    left: 50%;
+    transform: translate(-50%, -50%);
+  }
+}
+
+.icon-local { // 闪烁
+  position: absolute;
+  left: 50%;
+  transform: translate(-50%, -50%) rotateX(45deg);
+  display: inline-block;
+  width: 0.3vw;
+  height: 0.5vw;
+  margin: 0 0.5vw;
+  box-shadow: 0 0 0 0.3vw #ff000080;
+  border-radius: 50%;
+  animation: localShine 2s linear infinite;
+}
+
+@keyframes localShine{
+  from{
+    box-shadow:0 0 0 0 #ff000080
+  }
+  to{
+    box-shadow:0 0 0 3.1vw hsla(0,0%,100%,0)
+  }
+}
+
+.amap-info-content { // 高德内部样式修改
+  background-color: transparent;
+  box-shadow: none;
+}
+
+.amap-info-close { // 高德内部样式修改
+  margin-top: 2vh;
+  margin-right: .8vw;
+  font-size: 1vw;
+  display: none !important;
+}

+ 12 - 0
src/assets/styles/global.less

@@ -1,6 +1,18 @@
 @import "config.less";
+// 高德地图样式
+@import "amap.less";
 
 @font-face {
   font-family: DataFont;
   src: url("@/assets/fonts/YouSheBiaoTiHei.ttf");
 }
+
+// 关闭某个模块的事件
+.none-events {
+  pointer-events: none;
+}
+
+// 开启某个模块的事件
+.events {
+  pointer-events: all;
+}

+ 45 - 2
src/layouts/default/index.vue

@@ -1,7 +1,10 @@
 <template>
   <div id="default-layout">
     <Header />
-    <div>
+    <div class="cover none-events" style="margin: 0 auto;">
+      <div id="amap-container" class="events"></div>
+    </div>
+    <div class="view-page">
       <router-view />
     </div>
     <div class="action-panel-wrapper">
@@ -13,6 +16,8 @@
 <script>
 import Header from './modules/Header.vue'
 import ActionPanel from './modules/ActionPanel'
+import { AMapService } from '@/service/AMapService'
+
 export default {
   name: 'DefaultLayout',
   provide() {
@@ -20,6 +25,15 @@ export default {
       namespace: 'bei-data-v'
     }
   },
+  data: () => ({
+    mapService: null
+  }),
+  created() {
+    this.mapService = new AMapService((map) => {
+
+    })
+    this.mapService.loadMap('amap-container')
+  },
   components: {
     Header,
     ActionPanel
@@ -31,10 +45,39 @@ export default {
 #default-layout {
   width: 100vw;
   height: 100vh;
-  background-color: #0A153E;
+  background-color: #060e2b;
   background-image: url("@/assets/images/global-bg.png");
   background-repeat: no-repeat;
   background-size: 100% 100%;
+  
+ 
+  .cover {
+      position: relative;
+      width: 1600px;
+      height: 1160px;
+  }
+  
+  .cover:after {
+      position: absolute;
+      content: '';
+      width: 100%;
+      height: 100%;
+      top: 0;
+      left: 0;
+      box-shadow:0 0 80px 80px #060e2b inset;
+  }
+
+  #amap-container {
+    width: 1600px;
+    height: 1160px;
+  }
+
+  .view-page {
+    position: absolute;
+    top: 145px;
+    width: 100%;
+  }
+
   .action-panel-wrapper {
     position: absolute;
     bottom: 0;

+ 169 - 0
src/service/AMapService.js

@@ -0,0 +1,169 @@
+import AMapLoader from '@amap/amap-jsapi-loader'
+import { Router } from 'vue-router';
+
+const AMAP_KEY = "89185d69e5c6c07eae0b0ce8099db302";
+const AMAP_VERSION = "1.4.5"
+const AMAP_LOCA_VERSION = "1.3.2"
+
+// type LoadCallBack = (instance: MapService) => void;
+// interface PointData {
+//   marker?: any; // markData
+//   mouseover?: () => void // 鼠标移入事件
+//   mouseout?: () => void // 鼠标移出事件
+//   click?: () => void // 点击事件
+// }
+// interface SimplePointData {
+//   marker?: any; // markData
+// }
+
+export class AMapService {
+  /**
+   * 高德地图
+   */
+  amap;
+  AMap;
+  $router;
+  loadedCallback;
+
+  points = new Array();
+  simplePoints = new Array();
+
+  constructor($router,loadedCallback) {
+    this.$router = $router
+    // 初始化加载函数
+    this.loadedCallback = loadedCallback;
+  }
+
+  addSimplePoint(payload) {
+    this.callAmap((AMap, amap) => {
+      const marker = new AMap.Marker({
+        content: payload.content,
+        position: new AMap.LngLat( payload.position[0], payload.position[1]),   // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
+        title: payload.name,
+      });
+      const simplePoint = {
+        marker
+      }
+      this.simplePoints.push(simplePoint)
+      this.amap.add(marker)
+    })
+  }
+
+  addSimplePoints(payloads) {
+    payloads.forEach(payload => this.addSimplePoint(payload));
+  }
+  
+  loadMap(el) {
+    AMapLoader.load({
+      "key": AMAP_KEY,// 申请好的Web端开发者Key,首次调用 load 时必填
+      "version": AMAP_VERSION,// 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
+      "plugins": [
+        "AMap.Scale"
+      ],
+      "Loca":{ // 是否加载 Loca, 缺省不加载
+        "version": AMAP_LOCA_VERSION // Loca 版本,缺省 1.3.2
+      },
+      }).then((AMap)=>{
+          // 获取类
+          this.AMap = AMap
+          // 加载地图
+          this.amap = new AMap.Map(el, {
+              zoom: 13,//级别
+              pitch: 30,
+              center: [106.395593,29.805197],//中心点坐标
+              viewMode:'3D',  //使用3D视图
+          });
+          // 设置地图样式
+          this.amap.setMapStyle("amap://styles/dark")
+          this.amap.addControl(new AMap.Scale())
+          // 加载后的数据处理
+          this.loadedCallback(this);
+      }).catch(e => {
+          console.log(e);
+      })
+  }
+
+  addPoint(payload){
+    const that = this
+    this.callAmap((AMap, amap) => {
+      // 1、创建信息窗口
+      const infoWindow = new AMap.InfoWindow({
+        anchor: 'bottom',
+        content: payload.data.content(payload.data),
+        offset: new AMap.Pixel(8, -40),
+        position: payload.position
+      });
+      // 2、创建点位
+      const marker = new AMap.Marker({
+        content: payload.content,
+        position: new AMap.LngLat( payload.position[0], payload.position[1]),   // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
+        title: payload.name,
+      });
+      const point =  {
+        marker,
+        mouseover: function () {
+          infoWindow.open(amap);
+          document.querySelector(".amap-info-content")?.classList.remove("amap-info-outer")
+        },
+        mouseout: function () {
+          infoWindow.close();
+          document.querySelector(".amap-info-content")?.classList.remove("amap-info-outer")
+        },
+        click: function () {
+          that.$router.push('/detail/1')
+        }
+      }
+      // 3、创建点击事件,绑定点位与信息窗口的关系
+      marker.on("mouseover", point.mouseover)
+      marker.on("mouseout", point.mouseout)
+      marker.on("click", point.click)
+      this.points.push(point);
+      // 将点位添加到地图上
+      amap.add(marker);
+    })
+  }
+
+  /**
+   * 加载多个节点
+   * @param payloads 负载数据数组
+   */
+  addPoints(payloads) {
+    payloads.forEach(payload => this.addPoint(payload));
+  }
+
+
+  clearPoint() {
+    if(this.points && this.points.length > 0) {
+      this.points.forEach(point => {
+        this.removePoint(point)
+      })
+      this.points = new Array();
+    }
+  }
+
+
+
+  /**
+   * 移出点位
+   * @param point 
+   */
+  removePoint(point){
+    if (point) {
+      point.marker.off('mouseover', point.mouseover)
+      point.marker.off('mouseout', point.mouseout)
+      point.marker.off('click', point.click)
+      this.amap.remove(point)
+    }
+  }
+
+  /**
+   * 封装获取,处理操作
+   * @param callback 
+   */
+  callAmap(callback) {
+    const { AMap, amap } = this
+    if (AMap && amap) {
+      callback(AMap, amap)
+    }
+  }
+}

+ 1 - 1
src/views/detail/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div id="detail">
+  <div id="detail-view">
     <RightPanel />
     
     <LeftPanel />

+ 1 - 1
src/views/main/index.vue

@@ -1,5 +1,5 @@
 <template>
-  <div id="main">
+  <div id="main-view">
     <RightPanel />
     
     <LeftPanel />

+ 5 - 0
yarn.lock

@@ -11,6 +11,11 @@
     event-pubsub "4.3.0"
     js-message "1.0.7"
 
+"@amap/amap-jsapi-loader@^1.0.1":
+  version "1.0.1"
+  resolved "https://registry.npmmirror.com/@amap/amap-jsapi-loader/-/amap-jsapi-loader-1.0.1.tgz#9ec4b4d5d2467eac451f6c852e35db69e9f9f0c0"
+  integrity sha512-nPyLKt7Ow/ThHLkSvn2etQlUzqxmTVgK7bIgwdBRTg2HK5668oN7xVxkaiRe3YZEzGzfV2XgH5Jmu2T73ljejw==
+
 "@ampproject/remapping@^2.1.0":
   version "2.1.2"
   resolved "https://registry.npmmirror.com/@ampproject/remapping/-/remapping-2.1.2.tgz#4edca94973ded9630d20101cd8559cedb8d8bd34"