Przeglądaj źródła

openlayers 加载地图

Hwf 9 miesięcy temu
rodzic
commit
576957b001

+ 107 - 0
src/components/Map/YztMap/OpenLayersMap.ts

@@ -0,0 +1,107 @@
+// 引入OpenLayers的主模块
+import Map from 'ol/Map';
+import View from 'ol/View';
+import Projection from 'ol/proj/Projection';
+import { getWidth, getTopLeft } from 'ol/extent';
+import TileLayer from 'ol/layer/Tile';
+import WMTS from 'ol/source/WMTS';
+import WMTSTileGrid from 'ol/tilegrid/WMTS';
+import WMTSCapabilities from 'ol/format/WMTSCapabilities';
+import proj4 from 'proj4';
+import { register } from 'ol/proj/proj4';
+import { defaults } from 'ol/control';
+import axios from 'axios';
+
+interface Options {
+  center: number[];
+  zoom?: number;
+  maxZoom?: number;
+  minZoom?: number;
+}
+interface layerParam {
+  layerName: string;
+  styleName: string;
+  tilematrixset: string;
+  format: string
+}
+
+proj4.defs('EPSG:4490', '+proj=longlat +ellps=GRS80 +no_defs +type=crs');
+proj4.defs('EPSG:4525', '+proj=tmerc +lat_0=0 +lon_0=111 +k=1 +x_0=37500000 +y_0=0 +ellps=GRS80 +units=m +no_defs +type=crs');
+register(proj4);
+const commonUrl = import.meta.env.VITE_APP_BASE_API + '/api/oneShare/proxyHandler/mm/'
+const projection = new Projection({
+  code: 'EPSG:4490',
+  units: 'degrees'
+});
+const projectionExtent = [-180, -90, 180, 90];
+const size = getWidth(projectionExtent) / 256;
+const resolutions = [];
+for (let z = 2; z < 22; ++z) {
+  resolutions[z] = size / Math.pow(2, z);
+}
+
+export class OpenLayersMap {
+  private map: Map;
+  constructor(element: HTMLElement | string, options?: Options = {}) {
+    this.map = new Map({
+      controls: defaults({
+        zoom: false,
+        rotate: false
+      }),
+      layers: [],
+      target: element,
+      view: new View({
+        center: options.center && options.center.length === 2 ? [options.center[0], options.center[1]] : [110.90153121597234, 21.98323671981171],
+        zoom: options.zoom ? options.zoom : 9.6,
+        projection: projection,
+        maxZoom: options.maxZoom ? options.maxZoom : 18,
+        minZoom: options.minZoom ? options.minZoom : 1
+      })
+    });
+  }
+
+  formatXml(code: string, minZoom?: number, maxZoom?: number, zIndex?: number, visible?: boolean) {
+    const xml = new WMTSCapabilities();
+    this.getCapabilities(code).then((lists) => {
+      const mapData = xml.read(lists.data);
+      const layerParam: layerParam = {
+        layerName: mapData.Contents.Layer[0].Title,
+        styleName: mapData.Contents.Layer[0].Style[0].Identifier,
+        tilematrixset: mapData.Contents.TileMatrixSet[0].Identifier,
+        format: mapData.Contents.Layer[0].Format[0]
+      };
+      this.createWmsLayer(code, layerParam, minZoom, maxZoom, zIndex, visible);
+    });
+  }
+  // 请求接口获取地图信息
+  getCapabilities(code) {
+    return axios.get(commonUrl + code);
+  }
+  // 请求地图图片加载图层
+  createWmsLayer(code: string, layerParam: layerParam, minZoom?: number = 0, maxZoom?: number, zIndex?: number = -1, visible?: boolean = true) {
+    const source = new WMTS({
+      url: commonUrl + code,
+      crossOrigin: 'Anonymous',
+      layer: layerParam.layerName,
+      style: layerParam.styleName,
+      matrixSet: layerParam.tilematrixset,
+      format: layerParam.format,
+      wrapX: true,
+      tileGrid: new WMTSTileGrid({
+        origin: getTopLeft(projectionExtent),
+        resolutions: resolutions,
+        matrixIds: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21']
+      })
+    });
+    const layer = new TileLayer({
+      source: source,
+      zIndex: zIndex,
+      minZoom: minZoom,
+      maxZoom,
+      visible: visible
+    });
+    layer.set('layerName', code);
+
+    this.map.addLayer(layer);
+  }
+}

+ 166 - 0
src/components/Map/YztMap/index.vue

@@ -0,0 +1,166 @@
+<template>
+  <div class="map-container">
+    <div ref="mapRef" class="map-container"></div>
+    <!-- 右下工具  -->
+    <div v-show="mapState.showScale" class="zoom-text">{{ mapState.zoom }}级</div>
+    <div class="right-tool">
+<!--      &lt;!&ndash; 快捷缩放 &ndash;&gt;-->
+<!--      <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" style="margin-left: 5px" @click="changeScaleControl">尺</div>-->
+<!--      </div>-->
+<!--      &lt;!&ndash; 测距工具 &ndash;&gt;-->
+<!--      <div class="model-btn" @click="toggleRangingTool">-->
+<!--        {{ isRanging ? '关闭测距' : '开启测距' }}-->
+<!--      </div>-->
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import 'ol/ol.css';
+import { OpenLayersMap } from './OpenLayersMap';
+import QuickZoom from '../quickZoom.vue';
+
+interface Props {
+  activeMap: string;
+}
+const props = withDefaults(defineProps<Props>(), {});
+
+const mapRef = ref(null);
+const mapState = reactive({
+  center: [110.93154257997, 21.669064031332],
+  zoom: 9,
+  minZoom: 6,
+  maxZoom: 16,
+  isThreeDimensional: false,
+  // 是否显示比例尺
+  showScale: true
+});
+
+let yztMap;
+const isRanging = ref(false);
+
+const initMap = () => {
+  yztMap = new OpenLayersMap(mapRef.value, {
+    center: mapState.center,
+    zoom: mapState.zoom,
+    minZoom: mapState.minZoom,
+    maxZoom: mapState.maxZoom
+  });
+  yztMap.formatXml('YZT1715739306532');
+};
+// 设置地图层级
+const setMapZoom = (value) => {
+  if (!yztMap) return;
+  const view = yztMap.map.getView();
+  if (value === 1) {
+    view.setCenter([113.280637, 23.125178]);
+    view.setZoom(7);
+  } else if (value === 2) {
+    view.setCenter([110.93154257997, 21.6690640313328]);
+    view.setZoom(11);
+  } else if (value === 3) {
+    view.setCenter([110.93154257997, 21.669064031332]);
+    view.setZoom(12);
+  } else if (value === 4) {
+    view.setCenter([110.93154257997, 21.669064031332]);
+    view.setZoom(15);
+  } else if (value === 5) {
+    view.setCenter([110.93154257997, 21.669064031332]);
+    view.setZoom(16);
+  }
+};
+// 切换2D、3D
+const switchThreeDimensional = () => {
+  const view = yztMap.map.getView();
+  mapState.isThreeDimensional = !mapState.isThreeDimensional;
+  const pitch = mapState.isThreeDimensional ? 45 : 0;
+  view.setPitch(pitch);
+};
+// 加载事件
+onMounted(() => {
+  initMap();
+});
+</script>
+
+<style scoped>
+.map-container {
+  width: 100%;
+  height: 100%;
+  position: relative;
+  .zoom-text {
+    position: absolute;
+    bottom: 8px;
+    right: 75px;
+    font-size: 14px;
+  }
+  .right-tool {
+    position: absolute;
+    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;
+  }
+  :deep(.amap-logo),
+  :deep(.amap-copyright) {
+    display: none !important;
+  }
+  /* 自定义测距工具样式 */
+  :deep(.amap-ranger) {
+    background-color: #ffffff;
+    border: 1px solid #888888;
+    border-radius: 5px;
+    padding: 5px;
+  }
+
+  :deep(.amap-ranger .amap-toolbar) {
+    color: #333;
+    font-size: 12px;
+    padding: 5px;
+  }
+
+  :deep(.amap-ranger .amap-toolbar button) {
+    background-color: #022577;
+    color: #fff;
+    border: none;
+    border-radius: 4px;
+    padding: 5px;
+    margin-right: 5px;
+    cursor: pointer;
+  }
+
+  :deep(.amap-ranger .amap-toolbar button:hover) {
+    background-color: #1a3c75;
+  }
+
+  :deep(.amap-ranger .amap-toolbar .amap-toolbar-text) {
+    color: #444;
+    font-size: 14px;
+  }
+}
+</style>

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

@@ -1,6 +1,7 @@
 <template>
   <div class="global-map">
     <MapLogical v-if="activeMap === 'logical'" :mapData="mapData" />
+<!--    <YztMap v-else-if="activeMap === 'satellite2'" ref="map2Ref" :activeMap="activeMap" />-->
     <YMap v-else-if="activeMap === 'satellite2'" ref="map2Ref" :activeMap="activeMap" />
     <Map v-else ref="mapRef" :activeMap="activeMap" />
     <!--左侧菜单-->
@@ -14,6 +15,7 @@
 
 <script lang="ts" setup>
 import Map from '@/components/Map/index.vue';
+import YztMap from '@/components/Map/YztMap/index.vue';
 import YMap from '@/components/Map/YMap.vue';
 import MapLogical from '@/components/Map/MapLogical.vue';
 import { logicalData } from './data/mapData';