husq
2023-10-10 33d69f9ff8b7100494f873b405d0431ec95b2ada
地图图层更换功能添加
4 files modified
1 files added
303 ■■■■ changed files
src/assets/icons/stand.png patch | view | raw | blame | history
src/components/GMap.vue 2 ●●● patch | view | raw | blame | history
src/components/cesiumMap/cesium.vue 145 ●●●●● patch | view | raw | blame | history
src/hooks/use-cesium-tsa.ts 141 ●●●● patch | view | raw | blame | history
src/store/common.ts 15 ●●●●● patch | view | raw | blame | history
src/assets/icons/stand.png
src/components/GMap.vue
@@ -448,7 +448,7 @@
              }}</a-col>
            <a-col span="15">
              <a-select :showArrow="false" v-model:value="aircraSelected" :bordered="false" :options="aircraftList"
                :placeholder="aircraftList.length == 0 ? 'N/A' : '请选择'" :disabled="aircraftList.length == 0 ? true : false"
                :placeholder="aircraftList.length == 0 || deviceInfo.device?.mode_code == 14 || !deviceInfo.device ? 'N/A' : '请选择'" :disabled="aircraftList.length == 0 ? true : false"
                size="small" style="width:100%;background-color: #5d5f61;color: #fff;" @change="selectChange"></a-select>
            </a-col>
          </a-row>
src/components/cesiumMap/cesium.vue
@@ -2,8 +2,8 @@
  <div class="height-100 width-100 cesium" id="cesiumContainer"></div>
  <div v-if="centerConfig.type && !centerConfig.latitude" class="pointLongitude">在地图上点击绘制项目中心点</div>
  <div class="search">
    <a-auto-complete v-if="show" v-model:value="searchText" style="width: 200px;height: 100%;" placeholder="请输入地址" @select="enter"
      @change="searchLocation" :options='resultList'>
    <a-auto-complete v-if="show" v-model:value="searchText" style="width: 200px;height: 100%;" placeholder="请输入地址"
      @select="enter" @change="searchLocation" :options='resultList'>
    </a-auto-complete>
    <span class="search-icon" @click="() => show = !show">
      <SearchOutlined style="fontSize:24px; color: blue;" />
@@ -23,6 +23,23 @@
    <div class="2d" v-if="dimension === 2" @click="switchDimension('3D')">2D</div>
    <div class="3d" v-else @click="switchDimension('2D')">3D</div>
  </div>
  <a-popover placement="left" overlayClassName="popover-card">
    <template #content>
      <div class="map-img">
        <div class="stand-box" :class="{ 'active-icon': mapSetting.mode === 0 }" @click.self="setMap(0)"></div>
        <div class="satellite-box" :class="{ 'active-icon': mapSetting.mode === 1 }" @click.self="setMap(1)">
          <div class="road-line" :class="{'disabled': mapSetting.mode === 0}">
            <a-checkbox :disabled="mapSetting.mode === 0" v-model:checked="mapSetting.roadLine" style="color: #fff !important;" @change="roadChange">开启路网</a-checkbox>
          </div>
        </div>
      </div>
    </template>
    <div class="layer-icon">
      <div class="layer-btn">
        <div class="img"></div>
      </div>
    </div>
  </a-popover>
</template>\
<script setup lang="ts">
@@ -67,7 +84,7 @@
  }
}
const searchLocation = _.debounce(search, 500)
const { flyTo, addPoint, removeById, switchModel, dimension, zoonIn, zoonOut } = cesiumOperation()
const { flyTo, addPoint, removeById, switchModel, dimension, zoonIn, zoonOut, roadPattern, patternMap } = cesiumOperation()
const enter = (e: string) => {
  removeById('key')
  const filterItem = resultList.value.find(v => v.value === e)
@@ -99,7 +116,7 @@
const switchDimension = (type: string) => {
  switchModel(type)
}
const handleMouseDown = (fn:Function) => {
const handleMouseDown = (fn: Function) => {
  // clearInterval(timer.value)
  timer.value = setInterval(() => {
    fn(10)
@@ -108,7 +125,21 @@
const handleMouseUp = () => {
  clearInterval(timer.value)
}
const mapSetting = computed(() => store.state.common.mapSetting)
const setMap = (type: number) => {
  store.commit('SET_MAP_SETTING_MODE', type)
  patternMap()
}
const roadChange = (e:any) => {
  if (mapSetting.value.mode === 0) return
  store.commit('SET_MAP_SETTING_ROAD_LINE', e.target.checked)
  if (e.target.checked) {
    roadPattern(true)
  } else {
    roadPattern(false)
  }
}
const checked = ref(true)
</script>
<style scoped lang="scss">
@@ -141,6 +172,7 @@
  display: flex;
  align-items: center;
  height: 32px;
  .search-icon {
    padding: 5px;
    background-color: #fff;
@@ -159,7 +191,9 @@
  align-items: center;
  flex-direction: column;
  height: 32px;
  &-in, &-out {
  &-in,
  &-out {
    padding: 5px;
    background-color: #fff;
    height: 32px;
@@ -186,7 +220,102 @@
  justify-content: center;
}
.layer-icon {
  pointer-events: auto;
  position: absolute;
  box-sizing: border-box;
  width: 40px;
  height: 40px;
  padding: 3px;
  right: 20px;
  bottom: 120px;
  background: #fff;
  margin-top: 10px;
  border-radius: 50%;
  .layer-btn {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 0 4px 0 rgba(0, 0, 0, .6);
    cursor: pointer;
  }
  .img {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    background: url('../../assets//icons//satellite-icon.png') no-repeat center;
  }
}
.map-img {
  width: 240px;
  height: 120px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 5px;
  box-sizing: border-box;
  .stand-box {
    background: url('../../assets/icons/stand.png') no-repeat 100% 100%;
    width: 110px;
    height: 100%;
    box-sizing: border-box;
    position: relative;
  }
  .stand-box::after {
    content: '标准地图';
    position: absolute;
    bottom: 0;
    right: 0;
    color: #fff;
    font-size: 14px;
  }
  .satellite-box {
    background: url('../../assets/icons/satellite-icon.png') no-repeat 100% 100%;
    width: 110px;
    height: 100%;
    box-sizing: border-box;
    position: relative;
    .road-line {
      width: 100%;
      color: #fff;
      font-size: 14px;
      background: rgba(0,0,0,.5);
      :deep(.ant-checkbox-disabled + span) {
        color: #fff !important;
        opacity: .4;
      }
    }
    .disabled {
      cursor: no-drop;
    }
  }
  .satellite-box::after {
    content: '卫星地图';
    position: absolute;
    bottom: 0;
    right: 0;
    color: #fff;
    font-size: 14px;
    padding: 1px 2px;
    background-color: #2d8cf0;
  }
}
.active-icon {
  border: 2px solid #1180ff;
}
.switch:hover {
  color: #1180ff;
}
</style>
}</style>
src/hooks/use-cesium-tsa.ts
@@ -1,5 +1,6 @@
import { ELocalStorageKey, EDeviceTypeName } from '/@/types'
import * as Cesium from 'cesium'
import { useMyStore } from '/@/store'
import {
  getCurrentInstance,
} from 'vue'
@@ -32,7 +33,62 @@
var viewer: Cesium.Viewer | null = null
export function cesiumOperation () {
  let handler: Cesium.ScreenSpaceEventHandler
  const TDT_Token = 'c6eea7dad4fa1e2d1e32ec0e7c9735db'
  // 天地图Key
  // 天地图地图
  const TDT_IMG_C = 'https://{s}.tianditu.gov.cn/img_c/wmts?service=wmts&request=GetTile&version=1.0.0' +
      '&LAYER=img&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}' +
      '&style=default&format=tiles&tk=' + TDT_Token
  // 天地图注记
  const TDT_ZJ = 'https://{s}.tianditu.gov.cn/cia_c/wmts?service=wmts&request=GetTile&version=1.0.0' +
      '&LAYER=cia&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}' +
      '&style=default&format=tiles&tk=' + TDT_Token
  // 标准地图注记
  const TID_STAND = 'https://{s}.tianditu.gov.cn/vec_w/wmts?service=wmts&request=GetTile&version=1.0.0' +
  '&LAYER=img&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}' +
  '&style=default&format=tiles&tk=' + TDT_Token
  // 天地图图层变量
  const imageryProvider_tdt = new Cesium.WebMapTileServiceImageryProvider({
    url: TDT_IMG_C,
    layer: 'tdtImg_c',
    style: 'default',
    format: 'tiles',
    tileMatrixSetID: 'c',
    subdomains: ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7'],
    tilingScheme: new Cesium.GeographicTilingScheme(),
    tileMatrixLabels: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19'],
    maximumLevel: 50,
  })
  // 标准地图图层变量
  const imageryProvider_stand = new Cesium.UrlTemplateImageryProvider({
    url: 'https://t{s}.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c',
    subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
    // format: 'image/jpeg',
    // show: true,
    maximumLevel: 18,
    credit: 'stand_tc'
  })
  // 标准地图图层注解
  const imageryProvider_standZh = new Cesium.UrlTemplateImageryProvider({
    url: 'https://t{s}.tianditu.gov.cn/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=e45274b0235bb913eceb393aabbf9c9c',
    subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
    maximumLevel: 18,
    credit: 'stand_zj'
  })
  // 天地图中文注记加载
  const annotation = new Cesium.WebMapTileServiceImageryProvider({
    url: TDT_ZJ,
    layer: 'tdtZwImg_c',
    style: 'default',
    format: 'tiles',
    tileMatrixSetID: 'c',
    subdomains: ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7'],
    tilingScheme: new Cesium.GeographicTilingScheme(),
    tileMatrixLabels: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19'],
    maximumLevel: 50,
  })
  const dimension = ref(3)
  const store = useMyStore()
  const _init = () => {
    // Cesium Token
    const cesiumToken = import.meta.env.VITE_CESIUM_TOKEN
@@ -60,42 +116,19 @@
  }
  // 加载图层、注解方法
  const loadLAYER = () => {
    // 天地图Key
    const TDT_Token = 'c6eea7dad4fa1e2d1e32ec0e7c9735db'
    // 天地图地图
    const TDT_IMG_C = 'https://{s}.tianditu.gov.cn/img_c/wmts?service=wmts&request=GetTile&version=1.0.0' +
      '&LAYER=img&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}' +
      '&style=default&format=tiles&tk=' + TDT_Token
    // 天地图注记
    const TDT_ZJ = 'https://{s}.tianditu.gov.cn/cia_c/wmts?service=wmts&request=GetTile&version=1.0.0' +
      '&LAYER=cia&tileMatrixSet=c&TileMatrix={TileMatrix}&TileRow={TileRow}&TileCol={TileCol}' +
      '&style=default&format=tiles&tk=' + TDT_Token
    // 天地图图层加载
    const imageryProvider = new Cesium.WebMapTileServiceImageryProvider({
      url: TDT_IMG_C,
      layer: 'tdtImg_c',
      style: 'default',
      format: 'tiles',
      tileMatrixSetID: 'c',
      subdomains: ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7'],
      tilingScheme: new Cesium.GeographicTilingScheme(),
      tileMatrixLabels: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19'],
      maximumLevel: 50,
    })
    viewer?.imageryLayers.addImageryProvider(imageryProvider)
    // 天地图中文注记加载
    const annotation = new Cesium.WebMapTileServiceImageryProvider({
      url: TDT_ZJ,
      layer: 'tdtImg_c',
      style: 'default',
      format: 'tiles',
      tileMatrixSetID: 'c',
      subdomains: ['t0', 't1', 't2', 't3', 't4', 't5', 't6', 't7'],
      tilingScheme: new Cesium.GeographicTilingScheme(),
      tileMatrixLabels: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19'],
      maximumLevel: 50,
    })
    viewer?.imageryLayers.addImageryProvider(annotation)
    if (store.state.common.mapSetting.mode === 1) {
      viewer?.imageryLayers.addImageryProvider(imageryProvider_tdt)
    }
    // 标准地图加载
    if (store.state.common.mapSetting.mode === 0) {
      viewer?.imageryLayers.addImageryProvider(imageryProvider_stand)
      viewer?.imageryLayers.addImageryProvider(imageryProvider_standZh)
    }
    // 路线图加载
    if (store.state.common.mapSetting.roadLine === true && store.state.common.mapSetting.mode === 1) {
      viewer?.imageryLayers.addImageryProvider(annotation)
    }
  }
  // 清除所有标记点
@@ -160,18 +193,48 @@
    }
  }
  // 长按实现地图放大
  // 地图放大
  const zoonIn = (range:number) => {
    // 获取当前视角的高度
    const cameraHeight = viewer?.camera.positionCartographic.height
    const amout = Cesium.Math.sign(range) * cameraHeight / Math.log(cameraHeight)
    viewer?.camera.zoomIn(amout)
  }
  // 长按实现地图缩小
  // 地图缩小
  const zoonOut = (range:number) => {
    const cameraHeight = viewer?.camera.positionCartographic.height
    const amout = Cesium.Math.sign(range) * cameraHeight / Math.log(cameraHeight)
    viewer?.camera.zoomOut(amout)
  }
  // 生成或删除路网图层
  const roadPattern = (flag:boolean) => {
    if (store.state.common.mapSetting.mode === 0) return
    const imageryLayers = viewer?.scene.imageryLayers
    const tdtZwImg_c = imageryLayers?._layers.find(v => v.imageryProvider._layer === 'tdtZwImg_c')
    if (!flag) {
      viewer?.imageryLayers.remove(tdtZwImg_c)
    } else {
      viewer?.imageryLayers.addImageryProvider(annotation)
    }
  }
  // 切换不同背景图层
  const patternMap = () => {
    const imageryLayers = viewer?.scene.imageryLayers
    console.log(imageryLayers, 'imageryLayers')
    // 切换为标准图层
    if (store.state.common.mapSetting.mode === 0) {
      const tdtImg_c = imageryLayers?._layers.find(v => v.imageryProvider._layer === 'tdtImg_c')
      const tdtZwImg_c = imageryLayers?._layers.find(v => v.imageryProvider._layer === 'tdtZwImg_c')
      viewer?.imageryLayers.remove(tdtImg_c)
      viewer?.imageryLayers.remove(tdtZwImg_c)
    } else {
      const tdtStand_c = imageryLayers?._layers.find(v => v.imageryProvider.credit.html === 'stand_tc')
      const tdtStand_zj = imageryLayers?._layers.find(v => v.imageryProvider.credit.html === 'stand_zj')
      console.log(tdtStand_c, tdtStand_zj, '===========================')
      viewer?.imageryLayers.remove(tdtStand_c)
      viewer?.imageryLayers.remove(tdtStand_zj)
    }
    loadLAYER()
  }
  onMounted(() => {
    if (viewer) return
@@ -193,6 +256,8 @@
    switchModel,
    dimension,
    zoonIn,
    zoonOut
    zoonOut,
    roadPattern,
    patternMap
  }
}
src/store/common.ts
@@ -4,7 +4,12 @@
  projectId: null as string | null,
  dockSns: null as string | null,
  snList: [] as string[],
  projectName: '' as string
  projectName: '' as string,
  // 地图setting
  mapSetting: {
    mode: 0, // 0为标准地图, 1为卫星地图
    roadLine: true,
  },
})
export type RootStateType = ReturnType<typeof state>
const mutations: MutationTree<RootStateType> = {
@@ -21,6 +26,14 @@
  },
  SET_PROJECT_NAME (state, projectName: string) {
    state.projectName = projectName
  },
  // 设置地图模式
  SET_MAP_SETTING_MODE (state, mode: number) {
    state.mapSetting.mode = mode
  },
  // 设置地图路网
  SET_MAP_SETTING_ROAD_LINE (state, roadLine: boolean) {
    state.mapSetting.roadLine = roadLine
  }
}
export default {