Prechádzať zdrojové kódy

地图 比例尺、快捷缩放、2d3d切换

Hwf 11 mesiacov pred
rodič
commit
6947614767

+ 142 - 94
src/components/Map/index.vue

@@ -1,72 +1,73 @@
 <template>
   <div class="map-container">
     <div id="yztMap" class="map-container"></div>
-<!--    <el-button type="primary" class="btn" @click="switchMap('satellite')">切换卫星图</el-button>-->
-<!--    <el-button type="primary" class="btn" style="left: 150px" @click="removeLayers()">清除图层</el-button>-->
+    <!-- 右下工具  -->
+    <div v-show="mapState.showScale" class="zomm-text">{{ mapState.zoom }}级</div>
+    <div class="right-tool">
+      <!--快捷缩放-->
+      <QuickZoom :step="mapState.zoom" :min-step="mapState.minZoom" :max-step="mapState.maxZoom" @change-step="setMapZoom" />
+      <div class="flex" style="margin-top: 5px;">
+        <div class="model-btn" @click="switchThreeDimensional">{{ mapState.isThreeDimensional ? '3D' : '2D' }}</div>
+        <div class="model-btn" @click="changeScaleControl" style="margin-left: 5px;">尺</div>
+      </div>
+    </div>
   </div>
 </template>
 <script setup lang="ts">
-import { getMapProduct } from '@/api/globalMap';
-import WMTSManager from "@/utils/wmtsManager";
-import AMapLoader from "@amap/amap-jsapi-loader";
+import AMapLoader from '@amap/amap-jsapi-loader';
+import QuickZoom from './quickZoom.vue';
 
 interface Props {
-  center?: number[];
-  zoom?: number;
-  minZoom?: number;
-  maxZoom?: number;
   activeMap: string;
 }
 
-const props = withDefaults(defineProps<Props>(), {
+const props = withDefaults(defineProps<Props>(), {});
+
+const mapState = reactive({
   center: [110.93154257997, 21.669064031332],
   zoom: 11,
   minZoom: 6,
-  maxZoom: 16
+  maxZoom: 16,
+  isThreeDimensional: false,
+  // 是否显示比例尺
+  showScale: true
 });
-
-const { proxy } = getCurrentInstance() as ComponentInternalInstance;
-
-let map, wmtsManager, wmtslayergroup;
+let map, scale;
 
 // 初始化事件
-const initMapEvent = () => {
-  const simple = {
-    version: 8,
-    sources: {},
-    layers: []
-  };
-  const wgs84_wgs84_mapcrs = {
-    topTileExtent: [-180, -270, 180, 90],
-    coordtransform: 'none',
-    tileSize: 256
-  };
-  map = new GeoGlobe.Map({
-    mapCRS: wgs84_wgs84_mapcrs,
-    style: simple,
-    maxZoom: props.maxZoom,
-    zoom: props.zoom,
-    minZoom: props.minZoom,
-    center: props.center,
-    container: 'yztMap'
-  });
-  // style加载完成
-  map.on('style.load', function (e) {
-    const token = '3e25b8af23f8d5194175220fe67fe941';
-    const layer_vtc = new GeoGlobe.TDTLayer('vec_c', token);
-    const layer_cva = new GeoGlobe.TDTLayer('cva_c', token);
-    layer_vtc.metadata = { group: 'basemap' };
-    layer_cva.metadata = { group: 'basemap' };
-    map.addLayer(layer_vtc);
-    map.addLayer(layer_cva);
-    if (props.activeMap !== 'vectorgraph') {
-      removeLayers();
+const initMap = () => {
+  AMapLoader.load({
+    // key: 'ef9090f018b879c7b896b352c01816dd', // 申请好的Web端开发者Key,首次调用 load 时必填
+    key: '30d3d8448efd68cb0b284549fd41adcf', // 申请好的Web端开发者Key,首次调用 load 时必填
+    version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
+    plugins: ['AMap.Scale']
+  }).then((AMap) => {
+    map = new AMap.Map('yztMap', {
+      // 是否为3D地图模式
+      viewMode: '3D',
+      pitch: mapState.isThreeDimensional ? 45 : 0,
+      // 初始化地图级别
+      zoom: mapState.zoom,
+      // 初始化地图中心点位置
+      center: [mapState.center[0], mapState.center[1]],
+      // 是否可拖拽
+      dragEnable: true,
+      // 是否允许通过鼠标滚轮来缩放
+      scrollWheel: true
+    });
+    if (!['logical', 'vectorgraph'].includes(props.activeMap)) {
       switchMap(props.activeMap);
     }
+    scale = new AMap.Scale();
+    if(mapState.showScale) {
+      map.addControl(scale);
+    }
+    map.on('zoomchange', zoomChangeHandler);
   });
 };
 // 切换地图
 const switchMap = (type) => {
+  mapState.zoom = 11;
   let queryParamsArr = [];
   if (type === 'satellite') {
     queryParamsArr = [
@@ -79,59 +80,75 @@ const switchMap = (type) => {
       }
     ];
   }
-  if (!wmtsManager) {
-    wmtsManager = new WMTSManager(map);
-    wmtsManager.init();
-  }
-  wmtsManager.addWmtsLayers(queryParamsArr, (res) => {});
-  // AMapLoader.load({
-  //   // key: 'ef9090f018b879c7b896b352c01816dd', // 申请好的Web端开发者Key,首次调用 load 时必填
-  //   key: '30d3d8448efd68cb0b284549fd41adcf', // 申请好的Web端开发者Key,首次调用 load 时必填
-  //   version: '2.0' // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
-  // }).then(AMap => {
-  //   let map = new AMap.Map('yztMap', {
-  //     // 是否为3D地图模式
-  //     viewMode: '3D',
-  //     pitch: 0,
-  //     // 初始化地图级别
-  //     zoom: 9.4,
-  //     // 初始化地图中心点位置
-  //     // center: [props.center[0], props.center[1]],
-  //     center: [121.456493, 31.252764],
-  //     // // 是否可拖拽
-  //     // dragEnable: false,
-  //     // // 是否允许通过鼠标滚轮来缩放
-  //     // scrollWheel: false
-  //   });
-  //   // map.setFeatures([]);
-  //   var wms = new AMap.TileLayer.WMTS({
-  //     url: 'http://t0.tianditu.gov.cn/img_c/wmts',
-  //     // url: 'http://10.181.7.236:9988/api/oneShare/proxyHandler/mm/' + queryParamsArr[0].serverCode,
-  //     // blend: true,
-  //     // tileSize: 256,
-  //     params: {
-  //       Layer: "img",
-  //       Version: "1.0.0",
-  //       Format: "tiles",
-  //       TileMatrixSet: "w",
-  //       STYLE: "default",
-  //       tk: 'd31190edaa4190af833234ab7b1a6f27'
-  //     }
-  //   });
-  //   wms.setMap(map);
+  // map.setFeatures([]);
+  // var wms = new AMap.TileLayer.WMTS({
+  //   url: 'http://t0.tianditu.gov.cn/img_c/wmts',
+  //   // url: 'http://10.181.7.236:9988/api/oneShare/proxyHandler/mm/' + queryParamsArr[0].serverCode,
+  //   // blend: true,
+  //   // tileSize: 256,
+  //   params: {
+  //     Layer: "img",
+  //     Version: "1.0.0",
+  //     Format: "tiles",
+  //     TileMatrixSet: "w",
+  //     STYLE: "default",
+  //     tk: 'd31190edaa4190af833234ab7b1a6f27'
+  //   }
   // });
+  // wms.setMap(map);
 };
 
-// 清除图层
-const removeLayers = () => {
-  if (wmtsManager) {
-    wmtsManager.removeWmtsLayers();
+// 缩放级别变化
+const zoomChangeHandler = (event) => {
+  mapState.zoom = map.getZoom();
+};
+
+const changeScaleControl = () => {
+  mapState.showScale = !mapState.showScale;
+  if (mapState.showScale) {
+    map.addControl(scale);
+  } else {
+    map.removeControl(scale);
+  }
+};
+
+// 设置地图层级
+const setMapZoom = (value) => {
+  if (!map) return;
+  if (value === 1) {
+    map.setCenter([113.280637, 23.125178]);
+    map.setZoom(7);
+  } else if (value === 2) {
+    map.setCenter([110.93154257997, 21.6690640313328]);
+    map.setZoom(11);
+  } else if (value === 3) {
+    map.setCenter([110.93154257997, 21.669064031332]);
+    map.setZoom(12);
+  } else if (value === 4) {
+    map.setCenter([110.93154257997, 21.669064031332]);
+    map.setZoom(15);
+  } else if (value === 5) {
+    map.setCenter([110.93154257997, 21.669064031332]);
+    map.setZoom(16);
   }
 };
 
+// 切换2d、3d
+const switchThreeDimensional = () => {
+  mapState.isThreeDimensional = !mapState.isThreeDimensional;
+  const pitch = mapState.isThreeDimensional ? 45 : 0;
+  map.setPitch(pitch);
+};
+
 // 加载事件
 onMounted(() => {
-  initMapEvent();
+  initMap();
+});
+
+onUnmounted(() => {
+  if (!!map) {
+    map.off('zoomchange', zoomChangeHandler);
+  }
 });
 </script>
 <style scoped>
@@ -139,10 +156,41 @@ onMounted(() => {
   width: 100%;
   height: 100%;
   position: relative;
-  .btn {
+  .zomm-text {
+    position: absolute;
+    bottom: 8px;
+    right: 75px;
+    font-size: 14px;
+  }
+  .right-tool {
     position: absolute;
-    bottom: 20px;
-    left: 20px;
+    bottom: 50px;
+    right: 5px;
+  }
+  .model-btn {
+    background-color: #022577;
+    font-size: 14px;
+    color: #889ee9;
+    cursor: pointer;
+    padding: 3px 3px;
+    border-radius: 5px;
+  }
+  :deep(.amap-scalecontrol) {
+    left: unset !important;
+    background-color: unset !important;
+    right: 74px;
+  }
+  :deep(.amap-scale-text) {
+    width: 230px !important;
+    text-align: left !important;
+    font-size: 14px;
+    padding-left: 20px;
+  }
+  :deep(.amap-scale-middle) {
+    width: 228px !important;
+  }
+  :deep(.amap-scale-edgeright) {
+    left: 228px !important;
   }
 }
 </style>

+ 83 - 0
src/components/Map/quickZoom.vue

@@ -0,0 +1,83 @@
+<template>
+  <div class="flex">
+    <div class="scale-btn" @click="addStep">
+      <el-icon size="14"><Plus /></el-icon>
+    </div>
+    <div style="margin: 8px 0 6px;position: relative">
+      <el-slider
+        v-model="step"
+        :min="1"
+        :max="4"
+        vertical
+        height="100px"
+        @input="changeStep"
+      />
+      <div v-show="step === 1" class="tooltip">省</div>
+      <div v-show="step === 2" class="tooltip" style="bottom: 22px">市</div>
+      <div v-show="step === 3" class="tooltip" style="bottom: 54px">区</div>
+      <div v-show="step === 4" class="tooltip" style="bottom: 54px">县</div>
+      <div v-show="step === 5" class="tooltip" style="bottom: 88px">镇</div>
+    </div>
+    <div class="scale-btn" @click="reduceStep">
+      <el-icon size="14"><Minus /></el-icon>
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { CSSProperties } from 'vue';
+
+interface Mark {
+  style: CSSProperties;
+  label: string;
+}
+
+type Marks = Record<number, Mark | string>;
+const emits = defineEmits(['changeStep']);
+
+let step = ref(2);
+// 发生变化时
+const changeStep = (value) => {
+  console.log(122, value);
+  emits('changeStep', value);
+};
+// 增加
+const addStep = () => {
+  step.value = step.value + 1;
+  changeStep(step.value);
+};
+
+// 减少
+const reduceStep = () => {
+  step.value = step.value - 1;
+  changeStep(step.value);
+};
+</script>
+
+<style lang="scss" scoped>
+.flex {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+}
+.scale-btn {
+  background-color: #2971e1;
+  border-radius: 50%;
+  width: 20px;
+  height: 20px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+  cursor: pointer;
+  color: #fff;
+}
+.tooltip {
+  position: absolute;
+  left: -27px;
+  bottom: -12px;
+  background-color: #2d76e9;
+  color: #fff;
+  padding: 5px 10px;
+  font-size: 14px;
+}
+</style>

+ 10 - 11
src/views/globalMap/SwitchMapTool.vue

@@ -2,8 +2,8 @@
   <div>
     <div :class="open ? 'switch-box active' : 'switch-box'">
       <div class="expand-btn" @click="handleExpand">{{ open ? '收起' : '展开' }}</div>
-      <div class="switch-item" @click="selectItem('logical')">
-        <div v-if="open || (!open && activeMap === 'logical')" class="item-bg">
+      <div v-if="open || (!open && activeMap === 'logical')" class="switch-item" @click="selectItem('logical')">
+        <div class="item-bg">
           <div :class="activeMap === 'logical' ? 'item-text bg-active' : 'item-text'">逻辑地图</div>
         </div>
       </div>
@@ -22,18 +22,17 @@
 </template>
 
 <script lang="ts" setup>
-// interface Props {
-//   activeMap: boolean;
-// }
-//
-// const props = withDefaults(defineProps<Props>(), {});
+interface Props {
+  activeMap: string;
+}
+
+const props = withDefaults(defineProps<Props>(), {});
 
-const activeMap = ref('logical');
-const emits = defineEmits(['swtichMap']);
+const emits = defineEmits(['update:activeMap', 'swtichMap']);
 let open = ref(false);
 const selectItem = (key) => {
-  // if (activeMap.value === key) return;
-  activeMap.value = key;
+  if (props.activeMap === key) return;
+  emits('update:activeMap', key)
   emits('swtichMap', key);
 };
 const handleExpand = () => {

+ 6 - 1
src/views/globalMap/ToolBox.vue

@@ -1,9 +1,14 @@
 <template>
-  <SwitchMapTool @swtichMap="swtichMap2" />
+  55
 </template>
 
 <script lang="ts" setup>
 import SwitchMapTool from '@/views/globalMap/SwitchMapTool.vue';
+interface Props {
+  activeMap: string;
+}
+
+const props = withDefaults(defineProps<Props>(), {});
 const emits = defineEmits(['swtichMap']);
 const swtichMap2 = (key) => {
   emits('swtichMap', key);

+ 3 - 2
src/views/globalMap/index.vue

@@ -2,7 +2,7 @@
   <div class="global-map">
     <MapLogical v-if="activeMap === 'logical'" :mapData="logicalData" />
     <Map v-else :activeMap="activeMap"></Map>
-    <ToolBox @swtichMap="swtichMap" class="tool-box" />
+    <SwitchMapTool :activeMap="activeMap" @swtichMap="swtichMap" class="tool-box" />
   </div>
 </template>
 
@@ -11,6 +11,7 @@ import Map from '@/components/Map/index.vue';
 import MapLogical from '@/components/Map/MapLogical.vue';
 import { logicalData } from './data/mapData';
 import ToolBox from './ToolBox.vue';
+import SwitchMapTool from "@/views/globalMap/SwitchMapTool.vue";
 
 const mapData = reactive(logicalData);
 let activeMap = ref('satellite');
@@ -28,7 +29,7 @@ const swtichMap = (key) => {
   height: 100%;
   .tool-box {
     position: absolute;
-    right: 50px;
+    right: 72px;
     bottom: 50px;
     z-index: 10;
     color: #fff;